2015-03-02 127 views
22

我想出這個如何有效地計算飛行中的平均值(移動平均值)?

n=1; 
curAvg = 0; 
loop{ 
    curAvg = curAvg + (newNum - curAvg)/n; 
    n++; 
} 

我覺得這樣的亮點是:
- 它避免了大的數字(以及可能的溢出,如果你會總結,然後分)
- 您保存一個寄存器(未需要存儲金額)

問題可能出在求和誤差上 - 但我認爲一般應該有平衡的舍入和舍入數,所以誤差不應該大大加和。

您是否發現此解決方案存在任何缺陷? 你有更好的建議嗎?

+0

我不明白你的公式。對於接下來的'1 2'和'3',你會做'curAvg = 1.5 +(3 - 1.5)/ 2 = 1.5 + 0.75 = 2.25',這會是錯誤的? – IVlad 2015-03-02 22:53:53

+1

類似的問題:http://stackoverflow.com/questions/12636613/how-to-calculate-moving-average-without-keeping-the-count-and-data-total – 2015-03-02 22:54:54

+0

@IVlad:loop 1:curAvg = 0 + (1-0)/ 1 = 1;迴路2:curAvg = 1 +(2-1)/2=1.5; n = 2
迴路2:迴路3:curAvg = 1.5 +(3-1.5)/ 3 = 2; n = 3
迴路3: n = 4 – 2015-03-02 22:55:09

回答

14

您的解決方案本質上是「標準」最優的在線解決方案,用於保持平均運行軌跡而不存儲大筆金額,同時運行「在線」,即您可以一次處理一個號碼而無需返回其他號碼,並且只使用恆定數量的額外內存。如果你想要一個稍微優化的解決方案,以數值準確性爲代價,以「在線」爲代價,然後假設你的數字都是非負數,然後將數字從小到大排序,然後按順序處理它們,與現在一樣。這樣,如果你得到一堆數量非常小的數字,然後得到一個大的數字,那麼你將能夠準確地計算平均數而不會下溢,而不是如果你首先處理了大數。

-4

上面的公式是無稽之談。簡單的數學和精度將決定:

n是迭代計數器,AV運行平均,newVal是新價值

初始化n=0AV=0

((AV * n) + newVal)/(n+1) = AV 

沒有捷徑,你必須有所有的數字並將它們除以迭代的次數,但是您可以通過知道它的哪個迭代來重建其中的一個數字,這是保持運行總數或重新計算它的投入。重新計算的時間成本很高,存儲數量的代價可能是內存方面的低成本,並且重新計算的代碼肯定會比保存總計和迭代的內存位置更多。

+1

它們的表達方式完全相同。將AV加到你的窗體的分子上並減去AV,就得到了AV *(n + 1)+ newVal-AV)/(n + 1) 1)+(newVal - AV)/(n + 1) – Itai 2016-08-31 11:06:33

+2

你的解決方案在數學上是正確的,但你有一個額外的乘法。試着把一些數字,你會看到我的解決方案工作得很好......也許你也可以嘗試使用一些常識,並多一點謙虛。如果6 ppl認爲它是「標準最佳解決方案」,那麼寫出它可能是不正確的,這是「無稽之談」。 – 2016-09-05 09:01:18