如何以不同的顺序添加浮动,并始终获得相同的总数?

时间:2010-04-24 11:52:49

标签: floating-point math numerical

假设我有三个32位浮点值,abc,这样(a + b) + c != a + (b + c)。是否存在可能类似于Kahan summation的求和算法,它保证这些值可以按任何顺序求和,并且总是达到完全相同(相当准确)的总和?我正在寻找一般情况(即不是仅涉及3个数字的解决方案)。

任意精度算术是唯一的出路吗?我正在处理非常大的数据集,所以我想尽可能避免使用任意精度算术的开销。

谢谢!

3 个答案:

答案 0 :(得分:8)

有一个有趣的'全精度求和'算法here,它保证最终总和独立于求和的顺序(Python中给出的配方;但翻译起来应该不会太难到其他语言)。请注意,该链接中给出的配方并不完全正确:主累积循环很好,但在最后一步中,将累积的部分和的列表转换为单个浮点结果({的最后一行为了获得正确的舍入结果,需要比简单地求和部分和更加谨慎。{1}}配方)请参阅配方下面的注释和Python的实现(下面链接)以获得解决此问题的方法。

使用任意精度算术的形式来保存部分和(中间和被表示为'非重叠'的双倍和),但可能足够快,特别是当所有输入的幅度大致相同。并且它总是给出一个正确的舍入结果,因此准确性与您希望的一样好,并且最终总和与加数的顺序无关。它基于Jonathan Shewchuk的this paper(自适应精确浮点运算和快速稳健几何谓词)。

Python使用此算法实现math.fsum,它执行正确舍入的与顺序无关的求和;你可以看到Python使用的C实现here ---寻找math_fsum函数。

答案 1 :(得分:2)

通过一些关于你必须总和的术语的其他信息,你可以避免Shewchuk算法的开销。

在IEEE 754算术中,只要x-y(Sterbenz定理,正式证明here

y/2 <= x <= 2*y就是精确的

因此,如果您可以在订单中安排所有条款,使得每个部分金额都是上述形式,那么您将免费获得准确的结果。

我担心在实践中几乎没有机会进入确保发生这种情况的条件。交替的正数和负数随着幅度的增加可能会出现这种情况。

注意:原始问题是关于一种算法,无论求和顺序如何,都会产生相同的结果。马克的回答引发了“精确算法”方向的偏差,但是再次阅读你的问题,我担心当我建议重新排序术语时,我正在推动太多事情。你可能不能做你想做的事情,我的回答可能是偏离主题的。好吧,抱歉:)

答案 2 :(得分:-1)

在程序中进行算术运算时,我不太确定(a + b)+ c!= a +(b + c)。

然而,在当今硬件上使用浮点运算的经验法则是永远不要直接测试相等性。

无论你有什么应用,你应该选择一个足够小的epsilon并使用

(abs(a - b) < epsilon)

作为平等测试。