Enumerable#sum如何避免浮点舍入错误?

Eri*_*sen 5 ruby algorithm floating-point enumerable ieee-754

我在玩一些Ruby中浮点舍入错误的玩具示例,并且发现以下行为令我感到惊讶。

首先,一个不奇怪的例子,其中发生舍入错误:

numbers = Array.new(10, 0.1)
#=> [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]

numbers.inject(0, :+)
#=> 0.9999999999999999
Run Code Online (Sandbox Code Playgroud)

现在尝试使用Enumerable#sum

numbers.sum
#=> 1.0
Run Code Online (Sandbox Code Playgroud)

我在文档中唯一可以找到解释的提示是

sum方法可能不遵守“ +”方法(例如Integer#+)的方法重新定义。

因此我想有某种本机代码实现可以加快速度,但是我认为C浮点也受IEEE-754相关的不精确算法的影响。

在第二个示例中出现此行为的原因是什么?该sum方法如何避免舍入误差?

Eri*_*sen 0

阿马丹在评论中给出了答案。

对于浮点值,Enumerable#sum使用一种算法来补偿求和过程中累积的误差。

正如评论中提到的,源代码链接到本文,维基百科有一篇关于所描述算法的变体的文章,称为卡汉求和算法