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

时间:2015-03-02 22:48:58

标签: algorithm math average moving-average

我想出了这个

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

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

问题可能在于求和误差 - 但我认为通常会有平衡的向上舍入和向下舍入的数字,所以错误不应该大大加总。

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

3 个答案:

答案 0 :(得分:22)

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

答案 1 :(得分:0)

我已经使用这种算法很多年了。 循环是任何一种循环。也许是单独的网络会话,或者是真正的循环。要跟踪的点是当前计数(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

答案 2 :(得分:-9)

上面的公式是无稽之谈。简单的数学和精确度将决定:

n是迭代计数器,AV正在运行平均值,newVal是新值

初始化n=0AV=0

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

没有快捷方式,您必须拥有所有数字并将它们除以迭代次数,但是您可以通过知道它是哪个迭代来重建其中一个数字,这是保持运行总数或重新计算的结果 - 计算它。重新计算的时间成本很高,存储数量的成本可能是内存方面的低成本,重新计算的代码肯定会超过保存总数和迭代次数的内存位置。