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
.
The Math
class states this caveat:
Unlike some of the numeric methods of class
StrictMath
, all implementations of the equivalent functions of classMath
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.