JVM上的浮点运算是否会在所有平台上产生相同的结果?

Eam*_*.R. 57 java floating-point

我在一台运行在多台机器上的应用程序中使用Java,并且所有机器都需要为数学运算获得相同的结果.使用Java的浮点基元是否安全?或者我应该使用定点数学库?

Jon*_*eet 56

不一般,没有.但是,您可以使用strictfp表达式:

在FP-strict表达式中,所有中间值必须是浮点值集或双值集的元素,这意味着所有FP严格表达式的结果必须是IEEE 754算法在使用单格式和双格式表示的操作数上预测的结果.

在不是FP-strict的表达式中,为实现授予了一些余地,以使用扩展指数范围来表示中间结果; 粗略地说,净效应是在独占使用浮点值集或双值集可能导致上溢或下溢的情况下,计算可能会产生"正确答案".


ajb*_*ajb 27

除此之外strictfp,还StrictMath要求结果可以预测超越和其他功能.

  • +1提及StrictMath.请注意,尽管Math中的大多数方法似乎只是委托给StrictMath,但其中许多方法在运行时默默地被JVM内在函数替换.内在函数是特定于平台的. (11认同)
  • @ntoskrnl你能指点我参考或进一步阅读吗? (3认同)

Mis*_*hax 9

JVM应该始终如一地实施IEEE规范,并且该规范非常技术性和精确性.float和double的浮点元在所有平台上是相同的.

区别仅在于处理中间结果,并且虚拟机实现可以使用float-extended-exponent和double-extended-exponent格式,同时评估涉及同一执行帧内的本地的表达式.

所以如果你有像这样的代码:

double d1 = 0.342;
double d2 = 1.328479;
double d3 = 4.99384728796;
System.out.println(d1 * d2 / d3);
Run Code Online (Sandbox Code Playgroud)

并且这不在strictfp上下文中,您可能在运行时在不同的JVM之间存在差异.这是因为在表达式d1*d2/d3的评估中,d1*d2的中间结果用在表达式"中间结果"/ d3中,并且JVM可能使用float-extended-exponent和double-extended-exponent格式存储"中间结果".

要解决这个问题,您可以使用strictfp或StrictMath,因为其他人已在此处回答,或者避免在表达式中使用中间结果.一种方法是将任何中间结果存储在堆上.例如如下:

class MyClass {
    static double d1 = 0.342;
    static double d2 = 1.328479;
    static double d3 = 4.99384728796;
    static double intermediate_result = 0d;
    public static void main(String[] args) {
        intermediate_result = d1 * d2;
        System.out.println(intermediate_result / d3);
    }
}
Run Code Online (Sandbox Code Playgroud)