After upgrading to Java 1.8.0_20, our test system reported errors, but the code was not changed. I found out that calling Math.pow() with exactly the same input parameters gives different results on repeated calls. In Java 1.8.0_11, it behaves as expected and always returns the same value, but with Java 1.8.0_20 and later it sometimes returns slightly different values.
This is similar to the question Math.pow gives different results depending on the version of java , but differs in that the pow () results differ within the same virtual machine.
The following JUint test does not work when running 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); } }
The test is not interrupted under Java 1.8.0_11, or if the access point is disabled using -Xint . A rigorous mathematical version of pow () yields consistent results. I suspect that JIT Hotspot performs some optimizations that switch to another implementation of pow (), which gives different results for specific input values. The mathematical function must be deterministic and must give consistent and reproducible results.
Is this a bug or function?
source share