如何有效地计算平均值(移动平均值)?

Vit*_*tik 40 algorithm math average moving-average

我想出来了

n=1;
curAvg = 0;
loop{
  curAvg = curAvg + (newNum - curAvg)/n;
  n++;
}
Run Code Online (Sandbox Code Playgroud)

我认为这种方式的亮点是:
- 它避免了大数字(如果你总和然后除以可能溢出)
- 你保存一个寄存器(不需要存储总和)

问题可能在于求和误差 - 但我认为通常会有平衡的向上和向下舍入数,因此误差不会大大加总.

你看到这个解决方案有任何陷阱吗?你有更好的建议吗?

use*_*092 24

您的解决方案本质上是"标准"最佳在线解决方案,用于保持平均运行轨迹而不存储大笔金额以及"在线"运行时,即您可以一次处理一个号码而无需返回其他号码,而您只能使用恒定数量的额外内存.如果你想在数字精度方面略微优化解决方案,以"在线"为代价,那么假设你的数字都是非负数,那么先将数字从最小到最大排序,然后按顺序处理它们,你现在这样做.这样,如果你获得了一堆非常小的数字然后得到一个大数字,你就能够准确地计算平均值而不会下溢,而不是先处理大数字.


Sco*_*ott 8

我已经使用这个算法很多年了。循环可以是任何类型的循环。也许是单独的网络会话,也可能是真正的循环。重点是您需要跟踪的只是当前计数 (N) 和当前平均值 (avg)。每次收到新值时,应用此算法来更新平均值。这将计算出精确的算术平均值。它还有一个额外的好处,就是可以防止溢出。如果您有无数个大数需要平均,那么在除以 N 之前将它们全部相加可能会溢出。该算法避免了这个陷阱。

Variables that are stored during the computation of the average:
N = 0
avg = 0

For each new value: V
    N=N+1
    a = 1/N
    b = 1 - a
    avg = a * V + b * avg
Run Code Online (Sandbox Code Playgroud)