2014-11-04 19 views
6

Po aktualizacji do wersji Java 1.8.0_20 nasz system testowy zgłosił błędy, ale kod nie został zmieniony. Dowiedziałem się, że Math.pow() wywoływana z dokładnie tymi samymi parametrami wejściowymi daje różne wyniki przy zgłoszonych połączeniach. W języku Java 1.8.0_11 zachowuje się zgodnie z oczekiwaniami i zwraca zawsze tę samą wartość, ale w przypadku języka Java 1.8.0_20 i wyższych czasami zwraca nieco inne wartości.Math.pow daje różne wyniki po wielokrotnych połączeniach

Jest to podobne do pytania Math.pow yields different result depending on java version, ale inne, ponieważ wyniki pow() różnią się w obrębie jednej maszyny wirtualnej.

Poniższy test nie powiedzie się, gdy JUint prowadzony pod Java 1.8.0_20 i wyższy

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 nie powiedzie pod Java 1.8.0_11 lub jeśli hotspot jest włączony razem z -Xint. Ścisła wersja matematyczna pow() daje spójne wyniki. Podejrzewam, że hotspot JIT wykonuje pewne optymalizacje, które przełączają się na inną implementację pow(), co daje różne wyniki dla pewnych wartości wejściowych. Funkcja matematyczna powinna być deterministyczna i powinna dawać spójne i powtarzalne wyniki.

Czy to błąd lub funkcja?

Odpowiedz

8

znalazłem następujący raport o błędzie:

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

Jest to bardzo podobne w tym, że raporty operacji zmiennoprzecinkowej powracającego nieznacznie różne wyniki w kodzie JITed vs kod interpretowany.

Problem został oznaczony jako błąd i został naprawiony. Na tej podstawie twierdzę, że to, co widzisz, jest również błędem i powinno zostać zgłoszone Oracle.

Powiązane problemy