This just has to do with printing.
This is the TXR Lisp interactive listener of TXR 256.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
TXR works even if the application surface is not free of dirt and grease.
1> (+ 0.1 0.2)
0.3
OK, so then:
2> (set *print-flo-precision* 17)
17
3> (+ 0.1 0.2)
0.30000000000000004
But:
4> 0.1
0.10000000000000001
5> 0.2
0.20000000000000001
6> 0.3
0.29999999999999999
I.e. 0.1 isn't exactly 0.1 and 0.2 isn't exactly 0.2 in the first place! The misleading action is to compare the
input notation of 0.1 and 0.2 to the
printed output of the sum, rather than consistently compare nothing but values printed using the same precision.
The IEEE double format can store 15 decimal digits of precision such that all those decimal digits are recoverable. If we print values to no more than 15 digits, then things look "artificially clean" for situations like (+ 0.1 0.2).
I made *print-flo-precision* have an initial value of 15 for this reason.
The 64 bit double gives us 0.1, 0.2 and 0.3 to 15 digits of precision. If we round at that many digits, we don't see the trailing junk of representational error.
Unfortunately, to 15 digits of precision, the data type gives us two different 0.3's: the 0.299999... one and the 0.3.....04 one. Thus:
7> (= (+ 0.1 0.2) 0.3)
nil
That's the real kicker; not so much the printing. This representational issue bites you regardless of what precision you print with and is the reason why there are situations in which you cannot compare floating-point values exactly.