Will floating point operations on the JVM give the same results on all platforms?

JavaFloating Point

Java Problem Overview


I'm using Java in an application running on multiple machines, and all machines need to get the same results for mathematical operations. Is it safe to use Java's floating point primitives? Or should I just use a fixed-point math library?

Java Solutions


Solution 1 - Java

Not in general, no. However, you can use strictfp expressions:

> Within an FP-strict expression, all intermediate values must be elements of the float value set or the double value set, implying that the results of all FP-strict expressions must be those predicted by IEEE 754 arithmetic on operands represented using single and double formats. > > Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow.

Solution 2 - Java

In addition to strictfp, there's also StrictMath which requires that the results be predictable for transcendental and other functions.

Solution 3 - Java

The JVM should implement the IEEE specification consistently and this specification is very technical and precise. The floating point primitives of float and double are the same on all platforms.

The difference is only in the treatment of intermediate results, and that the virtual machine implementation may use float-extended-exponent and double-extended-exponent formats while evaluating expressions involving locals within the same frame of execution.

So if you have code like:

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

and this is not in a strictfp context, it is possible that you will have differences across different JVMs at runtime. This is because in the evaluation of the expression d1d2/d3 the intermediate result of d1d2 is used in the expression "intermediate result"/d3 and the JVM might be using float-extended-exponent and double-extended-exponent formats to store the "intermediate result".

To get around this, you can use strictfp or StrictMath as others have answered here, OR avoid using intermediate results in your expressions. One way to do that is to store any intermediate result on the heap. For instance as follows:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEamonn M.R.View Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaajbView Answer on Stackoverflow
Solution 3 - JavaMishaxView Answer on Stackoverflow