I am confused. If I calculate
System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);
Then I get a result of 0.9999999999999999
. But if I calculate
Double sum = DoubleStream.builder().add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).build().sum();
System.out.println(sum);
Then I get a result of 1.0
.
Why is there a difference?
The Javadoc of double java.util.stream.DoubleStream.sum() answers your question:
In particular, this method may be implemented using compensated summation or other technique to reduce the error bound in the numerical sum compared to a simple summation of double values.
In other words, the implementation of sum()
doesn't have to use simple summation of double values (which can have accuracy issues, as you noticed in your first snippet), and therefore may return a more accurate result.
EDIT: Note that even though using DoubleStream
's sum()
appears to give a more accurate result, this is an implementation detail, so it's not guaranteed by the Javadoc. Besides, simple double
addition is more efficient, since it doesn't have the overhead of constructing a DoubleStream
. You have to decide if you prefer potential better accuracy or performance.
Just to augment Eran's answer, internally DoubleStream#sum
uses Kahan Summation.
Relevant parts:
/**
* Incorporate a new double value using Kahan summation /
* compensation summation.
*
* High-order bits of the sum are in intermediateSum[0], low-order
* bits of the sum are in intermediateSum[1], any additional
* elements are application-specific.
*
*/
static double[] sumWithCompensation(double[] intermediateSum, double value) { ....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With