【问题标题】:Math.pow yields different results upon repeated callsMath.pow 在重复调用时会产生不同的结果
【发布时间】:2014-11-04 22:55:55
【问题描述】:

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

这类似于问题Math.pow yields different result depending on java version,但不同之处在于 pow() 的结果在一个 VM 内不同。

以下 JUint 测试在 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);
    }
}

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

这是错误还是功能?

【问题讨论】:

    标签: java math jvm-hotspot pow


    【解决方案1】:

    我发现了以下错误报告:

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

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

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

    【讨论】:

      【解决方案2】:

      这是一个错误。我将它报告给 ORACLE (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8063086),它被接受并在 Java 9 中得到修复。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-11
        • 2012-02-02
        • 2019-03-05
        • 2014-09-28
        • 1970-01-01
        • 2010-09-11
        • 2018-06-27
        相关资源
        最近更新 更多