我想出了这个想法
n=1;
curAvg = 0;
loop{
curAvg = curAvg + (newNum - curAvg)/n;
n++;
}
我认为这种方式的亮点如下:
- 它避免了大数字(如果您将它们加起来再除以数量会可能导致溢出)
- 您可以节省一个寄存器(不需要存储总和)
问题可能出在求和误差上 - 但是我假设整体上应该有近似相等数量的四舍五入,所以误差不应该累积得太多。
您是否看到这种解决方案中存在任何陷阱? 您有更好的建议吗?
我想出了这个想法
n=1;
curAvg = 0;
loop{
curAvg = curAvg + (newNum - curAvg)/n;
n++;
}
我认为这种方式的亮点如下:
- 它避免了大数字(如果您将它们加起来再除以数量会可能导致溢出)
- 您可以节省一个寄存器(不需要存储总和)
问题可能出在求和误差上 - 但是我假设整体上应该有近似相等数量的四舍五入,所以误差不应该累积得太多。
您是否看到这种解决方案中存在任何陷阱? 您有更好的建议吗?
您的解决方案本质上是保持平均值的标准最佳在线解决方案,而无需存储大量总和,同时“在线”运行,即每次只需处理一个数字,而无需回到其他数字,并且仅使用恒定数量的额外内存。如果您想获得稍微优化的数值精度解决方案,以“在线”的代价为前提,那么假设您的数字都是非负的,则首先将数字按从小到大排序,然后按照相同的方式进行处理。这样,如果您获得一堆大约相等的很小的数字,然后获得一个大数字,您将能够在不会下溢的情况下准确计算平均值,而不是处理大数字的情况下。
我已经使用这个算法很多年了。 循环可以是任何类型的循环。可能是单个Web会话,也可能是真实的循环。重点是只需要跟踪当前计数(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
1 2
和3
,接下来你会做curAvg = 1.5 + (3 - 1.5)/2 = 1.5 + 0.75 = 2.25
,这是错误的吗? - IVlad新平均值 = 旧平均值 + (下一个数据 - 旧平均值) / 下一个计数
。 - Donald_WcurAvg = 1.5 + (3-1.5) / 3 = 1.5 + 0.5 = 2
,这是正确的。 - Natesh Raina