在两个不同的JVM(Java 8和Java 17)之间进行平均时,相同值的差异是什么原因?
这是因为浮点数吗?还是两个版本之间有什么变化?
Java 17
public class Main {
public static void main(String[] args) {
List<Double> amountList = List.of(27.19, 18.97, 6.44, 106.36);
System.out.println("JAVA 17 result: " + amountList.stream().mapToDouble(x -> x).average().orElseThrow());
}
}
字符串
结果:39.7399999999995
Java 8
public class Main {
public static void main(String[] args) {
List<Double> amountList = Arrays.asList(27.19, 18.97, 6.44, 106.36);
System.out.println("JAVA 8 result: " + amountList.stream().mapToDouble(x -> x).average().orElse(0.0));
}
}
型
结果:39.740000000001
1条答案
按热度按时间dbf7pr2w1#
相关问题为JDK-8214761: Bug in parallel Kahan summation implementation
由于在此错误报告中提到
DoubleSummaryStatistics
也受到影响,因此我们可以构建一个消除所有其他影响的示例:字符串
我曾经制作过
的数据
(with Java 17的发布版本)
和
型
与backport of the fix的版本相匹配。
一般来说,方法的约定是,结果不一定要与仅将值相加并除以大小的结果相匹配。实现可以自由地提供错误纠正,但也必须记住,浮点加法不是严格关联的,但我们必须将其视为关联的,以便能够支持并行处理。
我们甚至可以验证这种变化是一种改进:
型
其打印,例如,
请注意,这是打印的十进制表示的错误。如果你想知道实际的
double
表示与正确值有多接近,你必须用new BigDecimal(average)
替换BigDecimal.valueOf(average)
。然后,错误之间的差异有点小,但是,新算法更接近两者的正确值。