Re: (* 2.4 3) => 7.2000003 WTF?! Let's Fix Lisp! Noob Programming Challenge



Kirk Sluder wrote:
perl -e "printf '%.20f', 7.20000000000001;"; echo ""
7.20000000000000994760

It looks like it is scaling the precision to the input.

Um, floats in perl are IEEE 754 double precision, which means that you
get < 16 decimal digits of precision (1 + epsilon == 1 for positive
epsilon < about 2.23 x 10^{-16}). So if you try to print anything
after that, you'll probably get garbage. printf should be smart enough
to realize that and stop you, but it doesn't.

Come on guys and gals, learn some stuff about floating-point, it's good
for you :) There are a number of options besides the traditional IEEE
754 style binary floating point:

* Extended (variable) precision floating point: see e.g. MPFR (Prof.
Fateman and I were working on a Lisp interface for MPFR -- anybody want
to help us finish it?)
* so-called "exact real arithmetic" based on continued fractions (see
e.g. Gosper; a while back there was a Lisp implementation available,
not sure about the status of that)
* FLI arithmetic (good for problems with huge numerical ranges, but
poor precision at the extreme ends of the representable range)

All of these have implementations; it's a programming exercise to link
them to Lisp if they aren't in Lisp already. Clisp already uses
something like MPFR for its LONG-FLOAT objects.

I'd suggest that if you want arithmetic to work sort of "like you
expect," just use MPFR objects, crank the precision really high and
only display the first few digits. That's the easy way to get around
not knowing much numerical analysis. (Hey, there's no shame in that;
Prof. Kahan of IEEE 754 fame estimated at a recent talk this year that
about one qualified numerical analyst is produced in the entire WORLD
each year.)

Poke me if you want some references on floating-point; I'd be glad to
give them to you.

mfh

.