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

How does Enumerable#sum avoid floating point rounding errors?

我在 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

现在用 Enumerable#sum 做同样的尝试:

numbers.sum
#=> 1.0

我在文档中唯一能找到的暗示解释的是

sum method may not respect method redefinition of “+” methods such as Integer#+.

所以我想有某种本地代码实现可以加快速度,但我假设 C 浮点数也受制于 IEEE-754 相关的不精确算法。

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

Amadan gave the answer in a .

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

如评论中所述,源代码链接到 this paper and Wikipedia has an article on a variation of the described algorithm known as the Kahan Summation Algorithm