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

时间:2014-03-11 19:43:45

标签: java floating-point

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

3 个答案:

答案 0 :(得分:56)

不一般,没有。但是,您可以使用strictfp expressions

  

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

     

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

答案 1 :(得分:27)

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

答案 2 :(得分:9)

JVM应始终如一地实施IEEE规范,并且此规范非常技术性和精确性。浮点和双的浮点基元在所有平台上相同。

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

所以如果您有以下代码:

double d1 = 0.342;
double d2 = 1.328479;
double d3 = 4.99384728796;
System.out.println(d1 * d2 / d3);

并且这不在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);
    }
}
相关问题