1.03 - .42 = ?
Item 31 of Joshua Bloch's Effective Java reads:
Avoid float and double if exact answers are required
And as an example, he used the following example:
System.out.println(1.03 - .42);
which prints
0.6100000000000001
I understand the reasoning behind the advice. No problem there.
Out of curiosity, I tried similar expressions in several different languages that's available on my Fedora Core 2 box. And the result is fascinating:
| Language | Expression | Result |
|---|---|---|
| C# | Console.WriteLine(1.03 - .42); | 0.61 |
| C++ | std::cout << 1.03 - 0.42 << std::endl; | 0.61 |
| Perl | print(1.03 - .42); | 0.61 |
| Python | print(1.03 - .42) | 0.61 |
| Ruby | print(1.03 - 0.42) | 0.61 |
| Guile | (display (- 1.03 .42)) | 0.61 |
What is going on here?
Re: 1.03 - .42 = ?
Weiqi, a Ph.D. Mathemetician, knows the answer already, but I will humor him.
<p/>
There are two problems here. One problem is that computer representation of real numbers is only approximate. Certain real numbers cannot be represented in binary floating-point arithmetic, for example, 1/5. The non-Java implementations are simply displaying fewer digits of the answer.
<p/>
The second problem is that significant digit discipline is not observed by the Java programmer, because of the default formatting used in the floating-point to String conversion. A decent explanation of this is found at mathworld
<p/>
I highly recommend that every Java developer buy and read Java Number Cruncher: The Java Programmer's Guide to Numerical Computing by Ronald Mak ISBN 0-13-046041-9.
<p/>
Also of note is work that is in progress to enhance the IEEE 754 spec with decimal floating-point math. This is in the works for Java in BigDecimal in 1.5 (or J2SE v5, or whatever it's called this week). It is also in the works for other languages. This will improve computer representation of decimal real numbers.