Ruby: sum vs. inject(:+) produces different results
Asked Answered
C

1

11

I've noticed array.sum and array.inject(:+) produce different results. What's the reason for this?

a = [10, 1.1, 6.16]

a.inject(:+)
# => 17.259999999999998

a.sum
# => 17.26
Croton answered 14/5, 2018 at 21:1 Comment(3)
Rounding - see "is floating point math broken" questions: sum probably uses native code; if so, it can be optimized, but also means it doesn't have to do the exact same sequence of rounding to a double-64 each step. What is the result of [10, 15, 1.1, 2, 6.16, 1].sum? What about 10 + 15 + 1.1 + 2 + 6.16 + 1? Those should show the same behavior "deviations" as the code in the question.Partida
The order in which these are added has an impact on what value you get out due to quirks of floating point values. I have a feeling sum works in a different order.Susurration
TIL we should prefer sum not only for performance but for accuracy when adding floating point numbers, thanks for this. It's pretty informative to look at the amount of complexity that exists in the C implementation of something as (seemingly) trivial as Array#sum.Roentgenogram
R
7

The C implementation of Array#sum delegates to the Kahan summation algorithm when some of its inputs are floating point numbers.

This algorithm ...

...significantly reduces the numerical error in the total obtained by adding a sequence of finite precision floating point numbers, compared to the obvious approach. This is done by keeping a separate running compensation (a variable to accumulate small errors).

-- Wikipedia

See Array#sum and the implementation on Github.

Roentgenogram answered 14/5, 2018 at 21:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.