2014-11-04 16 views
6

Nach dem Upgrade auf Java 1.8.0_20 hat unser Testsystem Fehler gemeldet, aber der Code wurde nicht geändert. Ich habe herausgefunden, dass Math.pow() mit genau den gleichen Eingabeparametern unterschiedliche Ergebnisse bei veralteten Aufrufen liefert. In Java 1.8.0_11 verhält es sich wie erwartet und gibt immer den gleichen Wert zurück, aber mit Java 1.8.0_20 und höher gibt es manchmal etwas andere Werte zurück.Math.pow liefert bei wiederholten Aufrufen unterschiedliche Ergebnisse

Dies ist ähnlich der Frage Math.pow yields different result depending on java version, aber anders, weil die Ergebnisse von pow() innerhalb einer VM unterscheiden.

Der folgende JUint Test schlägt fehl, wenn unter Java 1.8.0_20 und höher

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 scheitert nicht unter Java 1.8.0_11 oder wenn der Hotspot mit -Xint gedreht wird. Die strikte mathematische Version von pow() liefert konsistente Ergebnisse. Ich vermute, dass der Hotspot-JIT einige Optimierungen durchführt, die zu einer anderen Implementierung von pow() wechseln, was zu unterschiedlichen Ergebnissen für bestimmte Eingabewerte führt. Eine mathematische Funktion sollte deterministisch sein und konsistente und reproduzierbare Ergebnisse liefern.

Ist das ein Fehler oder eine Funktion?

Antwort

8

Ich habe den folgenden Fehlerbericht gefunden:

JDK-7021568 : Double.parseDouble() returns architecture dependent results

Es ist in sehr ähnlich ist, dass es meldet einen Gleitpunktoperation leicht unterschiedliche Ergebnisse in JITed Code vs interpretierten Code zurück.

Das Problem ist als Fehler markiert und wurde behoben. Auf dieser Grundlage würde ich argumentieren, dass das, was Sie sehen, auch ein Fehler ist und an Oracle gemeldet werden sollte.

Verwandte Themen