问题
I'm running the following code on a JDK Version 1.7.0_60:
System.out.println(Math.pow(1.5476348320352065, (0.3333333333333333)));
The result is: 1.1567055833133086
I'm running exactly the same code on a JDK Version 1.7.0.
The result is: 1.1567055833133089
I understand that double is not infinitely precise, but was there a change in the java spec that causes the difference?
PS: Because we use a legacy system, Big Decimal is not an option.
Edit: I was able to track down the time of the change: It was introduced in the JDK Version 1.7.0_40 (as compared to Version 1.7.0_25).
回答1:
but was there a change in the java spec that causes the difference?
No.* According to the Javadocs for Math.pow, a difference of up to one ULP (Unit in the Last Place) is permitted. If we take a look at your two values:
System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133086));
System.out.printf("%016x\n", Double.doubleToLongBits(1.1567055833133089));
we get:
3ff281ddb6b6e675
3ff281ddb6b6e676
which indeed differ by one ULP.
What you're seeing is probably due to slight differences in the sequence of floating-point instructions used by the JDK/JVM to implement these operations.
* At least, not so far as I know!
回答2:
There was no change in the spec, but there have been some changes in the hotspot optimizer that might (!) be related to this.
I dug up these code parts:
- From update 25: vm/opto/library_call.cpp : inline_pow
- From update 40: vm/opto/library_call.cpp : inline_pow
(these are not exactly the versions where these changes have been introduced, I just picked them because of the version information that you provided).
The changes (and what the code is doing at all) are far beyond what I can analyze in reasonable time, but maybe someone finds this reference interesting or useful.
回答3:
If you want repeatable floating point values between JVMs you can use the strictfp keyword, see following question When should I use the "strictfp" keyword in java?
回答4:
To produce consistent results between all Java versions, the solution was to use StrictMath.pow()
instead of Math.pow()
.
For background information on what might cause the difference, refer to this answer.
来源:https://stackoverflow.com/questions/25404088/math-pow-yields-different-result-depending-on-java-version