提问人:m81 提问时间:4/22/2015 更新时间:4/22/2015 访问量:673
平均浮点数时保持精度
Maintain precision when averaging floats
问:
假设我有大量的浮点数,例如 100 个,我需要计算它们的平均值。
为了得到最准确的结果,我应该将所有数字相加,然后除以 100 吗?
或者我应该将每个数字除以 100,然后将它们全部相加?
(如果重要的话,我正在用 Python 2 编码。
答:
3赞
Stephen Canon
4/22/2015
#1
将它们相加,然后除以 100。一个好的经验法则是,您通常可以通过执行较少的操作来最小化FP误差[1]。如果对它们求和然后除法,则已执行 100 次浮点运算。如果先除法再求和,则已执行 199 次浮点运算。
[1] 在一些例外情况下,多次计算的舍入误差会完全抵消,但这很少是偶然发生的——如果发生这种情况,通常是因为算法被设计为由知道自己在做什么的人以这种方式工作。
0赞
Gordon Linoff
4/22/2015
#2
我可以从一般的角度来回答这个问题,而不是从Python的角度来回答这个问题。问题的答案取决于几个因素,包括值的数量和值的范围。
你是对的,将数字加在一起会导致不好的结果。这称为数值不稳定算法。浮点运算会出现问题。在某些时候 x + 1 = x,因为 x + 1 没有表示。
但是,您可能不必担心 100 个数字,除非它们非常大。在处理数百万个数字时,更常出现此问题 - 或者您可能会遇到整数算术的溢出问题。
除以总数也不一定是解决方案,因为你可能在另一个方向上遇到问题——太小了。
一种更稳定的方法是对平均值进行迭代计算:
avg(1) = x1
avg(2) = avg(1) * (1/2) + x2 * (1/2)
avg(3) = avg(2) * (2/3) + x3 * (1/3)
. . .
avg(n) = avg(n - 1) * ((n - 1) / n) + (x(n) / n)
我应该注意的是,如果你的数字范围很广,你仍然会有问题。当您有非常大的正数和负数可以相互抵消时也是如此。在这种情况下,可能必须使用其他方法;这些通常考虑数字的大小和符号。
评论
4赞
Stephen Canon
4/22/2015
如果您担心累积的舍入误差,并且对先验值的分布一无所知,那么最好使用块累积(或 Kahan 求和)而不是迭代平均计算。
0赞
Aristotle Allen
4/22/2015
#3
先加平均值,然后平均值将得到最准确的平均值
如果您对准确性感兴趣,请使用 Decimal
评论
(a + b + c)/100
a/100 + b/100 + c/100
0.01