2014-11-04 88 views
6

升級到Java 1.8.0_20後,我們的測試系統報告了錯誤,但代碼沒有更改。我發現,使用完全相同的輸入參數調用Math.pow()可以在重新調用時產生不同的結果。在Java 1.8.0_11中,它的行爲與預期相同,並且返回的值始終相同,但對於Java 1.8.0_20及更高版本,它有時會返回稍微不同的值。Math.pow在重複調用時會得到不同的結果

這與問題Math.pow yields different result depending on java version類似,但不同,因爲pow()的結果在一個VM內不同。當的Java 1.8.0_20下運行和更高的

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沒有的Java 1.8.0_11下可能會失敗,或者如果熱點與-Xint打開的

以下JUint測試失敗。 pow()的嚴格數學版本會產生一致的結果。我懷疑熱點JIT做了一些優化,切換到pow()的不同實現,對某些輸入值產生不同的結果。數學函數應該是確定性的,並且應該產生一致和可重複的結果。

這是錯誤還是功能?

回答

相關問題