我很困惑。如果我算了
System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);
然后我得到0.9999999999999999
的结果。但是,如果我计算
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);
然后我得到1.0
的结果。
为什么会有区别?
答案 0 :(得分:10)
特别地,该方法可以使用补偿求和或其他技术来实现,以减少与双值的简单求和相比的数值和中的误差界限。
换句话说,sum()
的实现不必使用双值的简单求和(可能会出现准确性问题,正如您在第一个代码段中所注意到的那样),因此可能会返回{ {3}}
编辑:请注意,尽管使用double
' DoubleStream
似乎可以提供更准确的结果,但这是一个实施细节,因此Javadoc无法保证。此外,简单的{{1}}添加更有效,因为它没有构建{{1}}的开销。您必须决定是否更倾向于更好的准确性或性能。
答案 1 :(得分:2)
只是为了增加Eran的答案,内部DoubleStream#sum
使用Kahan Summation。
相关部分:
/**
* 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) { ....