2015-03-02 121 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