Search code examples
javamath

Different results of division on M3 Mac?


Assume the following class:

class Test {
    public static void main(String[] args) {
        double result = Math.log(9) / Math.log(3);
        System.out.println(result);
    }
};

On a x86_64 Linux machine (Linux 6.8.10-300.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Fri May 17 21:20:54 UTC 2024 x86_64 GNU/Linux), I get the following result:

2.0

On an M3 Mac, I get the following instead:

2.0000000000000004

What are possible explanations of this behavior, other than a JDK bug? The JDK version used on both machines is Temurin-21.0.3+9.


Solution

  • Feature, not a bug

    The Math class states this caveat:

    Unlike some of the numeric methods of class StrictMath, all implementations of the equivalent functions of class Math are not defined to return the bit-for-bit same results. This relaxation permits better-performing implementations where strict reproducibility is not required.

    This means that the implementation can vary by small amounts. So it is not a bug.

    Then you have to consider floating point arithmetic. We can do the real arithmetic,

    log(9)/log(3) = log(3^2)/log(3) = 2 log(3)/log(3) = 2
    

    Java is not going to make these reductions for you, it is going to calculate log(9) which does not have a non-terminating exact binary representation. Then log(3) and then perform the division. So there are a couple approximations happening.