2015-07-12 88 views
3

我有數據收集,其中每條記錄都有關於記錄此記錄時的車輛速度和時間的信息。每個記錄之間的時差是不同的,大約是300毫秒。我使用這個集合來計算旅行距離。我想修剪這個集合,而不會有太多的計算精度損失。有沒有任何算法?修剪集合用於計算距離

我試圖編寫一個簡單的算法,刪除記錄,如果記錄沒有不同於前一個至少X%。這個算法運行不好。例如,當我使用3%和4%修整算法時,記錄數是相同的,但計算距離在500米距離處相差40​​米,其中4%更準確。

編輯:本傑明算法的變化:

我有時間收集記錄的時候,所以我需要3條記錄。

double timeDifference = (next.time - curr.time)/(curr.time - previous.time); previuos.value = (previous.value + curr.value * timeDifference)/2

而且我不希望的結果是雙,但長,所以我需要使用舍入,這將改變距離。另外一分鐘約300條記錄,所以我希望四捨五入不會影響計算。

+0

,如果你需要的精度你可以使用BigDecimal的,但是這會降低性能,但也許並不適合你沒關係。 –

回答

2

你有值對的列表,即:

time | speed 
1: 0 | 0 
2: 300 | 10 
3: 600 | 40 
4: 900 | 48 
5: 1200 | 50 
6: 1500 | 30 
7: 1800 | 0 

你總是需要看兩個值ii-1。我們開始在i=1因爲否則我們會訪問索引-1

for(int i=1; i<list.size(); i++) { 
    if(Math.abs(list.get(i).speed - list.get(i-1).speed) < 3) { 
    list.get(i-1).time = (list.get(i).time + list.get(i-1).time)/2; 
    list.get(i-1).speed = (list.get(i).speed + list.get(i-1).speed)/2; 
    list.remove(i); 
    } 
} 

在口頭上:如果ii-1之間的速度差小於3,則更新條目i-1並設置其時間和速度,以平均ii-1。之後,我們從列表中刪除項目i

發生了示例數據什麼:此代碼刪除條目5:從數據。例如,因爲abs(50-48) = 22 < 3,並設置條目4:time = 1150speed = 49

上面的例子當然具有至少兩個問題(很容易解決 - 例如你的作業):1.如果列表只有一個條目,代碼將拋出一個異常。 2.移除項目後,list.size()發生變化,但上面的代碼無法識別該項目。這意味着:刪除任何條目後,它將引發異常。

我還沒有測試過,它只是爲了告訴你如何清理列表。

您可以額外添加一些代碼,防止從列表中刪除最後一個條目,否則您可能不會有確切的上次值。也可以在相同的數據上運行多次,直到list.size()保持不變。

(看看下面的評論)

+0

雖然我覺得這是一個很好的解決方案,但我有一個問題:爲什麼只是'3'?我的意思是,它是一個參數,還是有一個統計上有效的方法來計算它,根據可用的數據? –

+1

'3'因爲我覺得'3' ;-)你可以用你喜歡的任何東西代替'if'條件。你也可以用百分比計算兩個值之間的差異,然後看看它是否小於20%或任何你喜歡的。代碼應該只顯示,如何比較列表中的兩個值,計算並設置平均值並刪除一個條目。 (順便說一句:'speed'和'3'不能有任何關聯,因爲沒有人知道它是km/h,mp/h還是seamiles per second,or or or ...) –

+0

我的解決方案非常糟糕,有很多的情況下,它不會檢測到,它可能會產生不良的數據。 ** 1。**在該示例中,它將刪除最大值。速度,這可能很重要。 ** 2。**當速度條目類似於'0,1,2,1,0'時,結果將是'0.5625',這是完全沒有意義的。 ** 3。**當加速度上升或下降時,最好檢測最大值和最小值,即:'0,2,0'。這些數據有更多的信息!當然這會使算法更加複雜。 –

0

如果您不需要保留的歷史,你可以簡單地在新的數據被檢索更新行駛距離。我不知道你如何做微積分,我寫了我能想到的第一個例子。

Measurement record = null; 
double distance = 0; 
long totalTime = 0; 

// New record handler 
public void recordListener(Measurement newRecord) { 
    if(record != null) { 
     double avgSpeed = (record.speed + newRecord.speed)/2.0; 
     long timeDelta = newRecord.time - record.time; 
     distance += avgSpeed * (timeDelta/1000) // millis to seconds 
     totalTime += timeDelta; 
    } 
    record = newRecord; 
} 
+0

我不能這樣做,因爲數據流如下:收集數據 - >修剪它們 - >發送它們在服務器上 - >計算距離 – Amsik

+0

這個流程只執行一次或定期執行? – Shepard