Math.pow在重复调用时会产生不同的结果 [英] Math.pow yields different results upon repeated calls

查看:150
本文介绍了Math.pow在重复调用时会产生不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到Java 1.8.0_20后,我们的测试系统报告错误,但代码未更改。我发现,使用完全相同的输入参数调用的 Math.pow()会在重新调用的调用时产生不同的结果。在Java 1.8.0_11中,它的行为与预期的一样,并且总是返回相同的值,但是对于Java 1.8.0_20及更高版本,它有时会返回稍微不同的值。



这类似于问题 Math.pow根据java版本产生不同的结果,但不同,因为pow()的结果在一个VM中不同。



在Java 1.8.0_20及更高版本下运行时,以下JUint测试失败

  import static org.junit.Assert.assertEquals; 

import java.util.function.BiFunction;

import org.junit.BeforeClass;
import org.junit.Test;

公共类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(最终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);
}
}

在Java 1.8.0_11下测试不会失败或者如果使用 -Xint 启用热点。 pow()的严格数学版本产生一致的结果。我怀疑热点JIT做了一些优化,切换到pow()的不同实现,这对某些输入值产生不同的结果。数学函数应该是确定性的,并且应该产生一致且可重复的结果。



这是一个错误还是一个特征?



JDK-7021568:Double.parseDouble()返回架构相关结果



它非常相似因为它报告了一个浮点运算,在JITed代码和解释代码中返回的结果略有不同。



该问题被标记为错误并已修复。在此基础上,我认为你所看到的也是一个bug,应该报告给Oracle。


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?

解决方案

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.

这篇关于Math.pow在重复调用时会产生不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆