After upgrading to Java 1.8.0_20 our test system reported errors, but the code was not changed. I found out, that Math.pow()
called with exactly the same input parameters yields different results upon repreated calls. In Java 1.8.0_11 it behaves as expected and returns always the same value, but with Java 1.8.0_20 and above it sometimes returns slightly different values.
This is similar to the question Math.pow yields different result depending on java version, but different because the results of pow() differ within one VM.
The following JUint test fails when run under Java 1.8.0_20 and higher
import static org.junit.Assert.assertEquals;
import java.util.function.BiFunction;
import org.junit.BeforeClass;
import org.junit.Test;
public class PowerTest {
private static final int N = 1000000;
private static final double base = 5350.456329377186;
private static final double exp = 2.0;
private static double eval(final BiFunction<Double, Double, Double> f) {
return f.apply(base, exp);
}
private void loop(final BiFunction<Double, Double, Double> f) {
final double x = eval(f);
for (int i = 0; i < N; i++) {
final double p = eval(f);
assertEquals("i=" + i, x, p, 0);
}
}
@BeforeClass
public static void info() {
System.out.println("Java " + System.getProperty("java.version"));
}
@Test
public void mathPow() {
loop(Math::pow);
}
@Test
public void strictMathPow() {
loop(StrictMath::pow);
}
}
Test does not fail under Java 1.8.0_11 or if the hotspot is turned of with -Xint
. The strict math version of pow() yields consistent results. I suspect the hotspot JIT to do some optimizations that switch to a different implementation of pow(), which yields different results for certain input values. A mathematical function should be deterministic and should yield consistent and reproducible results.
Is this a bug or a feature?
It is a bug. I reported it to ORACLE (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8063086), it was accepted and is fixed in Java 9.
I have found the following bug report:
JDK-7021568 : Double.parseDouble() returns architecture dependent results
It is very similar in that it reports a floating-point operation returning slightly different results in JITed code vs interpreted code.
The issue is marked as a bug and has been fixed. On this basis I would argue that what you're seeing is also a bug and should be reported to Oracle.