Dam*_*num 37 java math floating-point pow
我在JDK版本1.7.0_60上运行以下代码:
System.out.println(Math.pow(1.5476348320352065, (0.3333333333333333)));
Run Code Online (Sandbox Code Playgroud)
其结果是:1.1567055833133086
我在JDK版本1.7.0上运行完全相同的代码.
其结果是:1.1567055833133089
我知道double并不是无限精确,但java规范中是否有变化会导致差异?
PS:因为我们使用遗留系统,所以Big Decimal不是一个选项.
编辑:我能够追踪更改的时间:它是在JDK版本1.7.0_40中引入的(与版本1.7.0_25相比).
Oli*_*rth 41
但java规范是否有变化导致差异?
没有.* 根据Javadocs的说法,Math.pow允许最多一个ULP(最后一个单位)的差异.如果我们看一下你的两个值:
System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133086));
System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133089));
Run Code Online (Sandbox Code Playgroud)
我们得到:
3ff281ddb6b6e675
3ff281ddb6b6e676
Run Code Online (Sandbox Code Playgroud)
确实相差一个ULP.
您所看到的可能是由于JDK/JVM用于实现这些操作的浮点指令序列略有不同.
规范没有变化,但热点优化器中有一些可能(!)与此相关的变化.
我挖出了这些代码部分:
(这些并不是引入这些更改的版本,我只是因为您提供的版本信息而选择它们).
这些变化(以及代码所做的事情)远远超出了我在合理时间内可以分析的变化,但也许有人认为这个参考有趣或有用.
小智 5
如果您想在JVM之间使用可重复的浮点值,可以使用strictfp关键字,请参阅以下问题我何时应该在java中使用"strictfp"关键字?