Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Math.pow yields different results upon repeated calls

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?

like image 236
Adam Avatar asked Nov 04 '14 22:11

Adam


2 Answers

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.

like image 152
NPE Avatar answered Sep 28 '22 02:09

NPE


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.

like image 26
Adam Avatar answered Sep 28 '22 01:09

Adam