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

我在多台机器上运行的应用程序中使用Java,所有机器都需要得到相同的math运算结果。 使用Java的浮点基元是否安全? 还是应该使用定点math库?

不一般,不。 但是,您可以使用strictfpexpression式 :

在FP-strictexpression式中,所有中间值必须是float值集或double值集的元素,这意味着所有FP-strictexpression式的结果必须是由IEEE 754algorithm在使用单格式和双格式表示的操作数上预测的结果。

在一个不是FP严格的expression式中,为了使用扩展的指数范围来表示中间结果,实现了一些余地。 总的来说,净效应是在独占使用float值集或double值集可能导致溢出或下溢的情况下,计算可能产生“正确答案”。

除了strictfp ,还有StrictMath ,它要求结果对于超越和其他函数是可预测的。

JVM应该一致地实现IEEE规范,这个规范是非常技术和精确的。 float和double的浮点基元在所有平台上都是相同的。

区别只在于处理中间结果,虚拟机实现可以使用浮点型扩展指数和双扩展型指数格式,同时在同一个执行框架内计算涉及本地的expression式。

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

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

这不是在严格的上下文中,有可能在运行时跨越不同的JVM。 这是因为在expression式d1 * d2 / d3的评估中,在expression式“中间结果”/ d3中使用d1 * d2的中间结果,并且JVM可能使用浮点扩展指数和双扩展指数格式存储“中间结果”。

为了解决这个问题,你可以使用strictfp或StrictMath作为别人在这里的回答,或者避免在expression式中使用中间结果。 一种方法是将任何中间结果存储在堆上。 比如如下:

 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); } }