Interestingly, though, some languages get it right:
northrup@Topaz:~/Desktop$ perl -de1
Loading DB routines from perl5db.pl version 1.55
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(-e:1): 1
DB<1> say 0.1 + 0.2
0.3
[…]
northrup@Topaz:~$ csi
CHICKEN
(c) 2008-2019, The CHICKEN Team
(c) 2000-2007, Felix L. Winkelmann
Version 5.1.0 (rev 8e62f718)
linux-unix-gnu-x86-64 [ 64bit dload ptables ]
#;1> (+ 0.1 0.2)
0.3
[…]
northrup@Topaz:~$ sbcl
This is SBCL 1.5.8, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (+ 0.1 0.2)
0.3
That's a fair point about the Perl example, but Scheme and Common Lisp (including both Chicken and SBCL, last I checked) support (if not outright require) full numeric towers with rational number types, so these are indeed exact representations (unless you explicitly request binary floats for e.g. performance reasons) and not just rounding during printing.
There are lots of other examples of doing it "right" (using more suitable numeric types) over at https://0.30000000000000004.com/ (alongside a bunch of examples that, to your point, just round, or to the GP's point, just stick to binary floats).
Yeah, in CL the 0.1 is read syntax for a float (IEEE-754ish on most modern implementations.) If you want exactly 0.1, you’d have to say 1/10. The printer is probably cheating and rounding to the output you expect (I think Python 3 may do this now?)
Aside from financial applications, there’s very little reason to care about the trailing remainder.
> The printer is probably cheating and rounding to the output you expect
northrup@Topaz:~$ sbcl
This is SBCL 1.5.8, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (= (+ 0.1 0.2) 0.3)
T
* (= (- (+ 0.1 0.2) 0.3) 0)
T
> Aside from financial applications
"Financial applications" happen to be pretty common reasons for number crunching :)
northrup@Topaz:~$ sbcl
This is SBCL 1.5.8, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (- 0.3 3/10)
0.0
* (= (- 0.3 3/10) 0)
T
* (= (- 3/10 0.3) 0)
T
* (= 0.3 3/10)
NIL
So yeah, 0.3 and 3/10 are definitely distinct, but still apparently net out to exactly 0 nonetheless.
Scheme is the same. If you type a number with a dot in it, you'll get an "inexact" number, which is floating point. If you prefix it with #e, you'll get an exact representation of the entered number (so, e.g. #e0.1 gives you 1/10)
The output of inexact numbers is typically truncated. In CHICKEN, you can use flonum-print-precision to tweak that. In an example, straight from the manual:
Per my other comment, SBCL's defaults still cause (= (- (+ 0.1 0.2) 0.3) 0) → T. I guess they're technically floats (or at the very least not rationals) given that (= 0.3 3/10) → NIL.
I don't think it's so much a matter of getting it right as much as it is about preferring the performance gain and ease of use of hardware-accelerated constant-space floating-point numbers. At least, that was probably the case when programming in something like C/C++. I don't imagine there's much point to it in ruby or python for example, other than that floating-point is standard by now.