Strange arithmetics

exercise No. 204

Q:

From ordinary arithmetics we expect a + b - c = a - c + b. But executing the subsequent code yields:

Code Output
System.out.println(1000000000 + 0.000000001 - 1000000000);
System.out.println(1000000000 - 1000000000 + 0.000000001);
0.0
1.0E-9

Explain these two different results.

A:

Short answer: The two values 1000000000 or 10 9 and 0.000000001 or 10 -9 differ by 18 orders of magnitude. An eight byte double cannot express enough digits for expressing this.

Longer answer: For summing up the int literal 1000000000 gets being converted into a double value being represented as 8 byte IEEE 754. Due to its inherently limited precision the above sums gets truncated. We consider:

Code Output
System.out.println(1000000000 == 1000000000 + 0.000000001);
true
System.out.println(1000000000.0 == 1000000000 + 0.000000001);
true

Thus in 8 byte IEEE 754 representation both 1000000000.0 and the expression 1000000000 + 0.000000001 amount to the exact same value. Evaluating from left to right we thus have:

  • 1000000000 + 0.000000001 - 1000000000 = 1000000000.0 - 1000000000 = 0.0.

  • Since 1000000000 is an int literal we have 1000000000 - 1000000000 == 0 and thus:

    1000000000 - 1000000000 + 0.000000001 = 0 + 0.000000001 = 1.0E-9.