2014-11-04 31 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()的不同实现,对某些输入值产生不同的结果。数学函数应该是确定性的,并且应该产生一致和可重复的结果。

这是错误还是功能?

回答

相关问题