Re: Numerical equality bug

 new new list compose Reply to this message Top page
+ (text/plain)

Delete this message
Author: Kaz Kylheku
To: vapnik spaknik
CC: txr-users
Subject: Re: Numerical equality bug
On 2022-02-05 10:02, vapnik spaknik wrote:
> This looks serious:
> 1> (- 1183.68 9.07)
> 1174.61
> 2> (= (- 1183.68 9.07) 1174.61)
> nil
> 3> (/= (- 1183.68 9.07) 1174.61)
> t
> 4> (< (- 1183.68 9.07) 1174.61)
> nil
> 5> (> (- 1183.68 9.07) 1174.61)
> t

If you try it in C and various languages, you get the same thing.

In TXR Lisp, I set the default floating point printing precision to 15
on purpose, so that most floating-point numbers "look good" due to being
rounded off to the decimal value you expect.

If you crank it up to 17 or more, you can see what is going on with
the least significant bits of the 52 digit manitssa:

This is the TXR Lisp interactive listener of TXR 273.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
TXR is made with 75% post-consumer recycled cons cells.
1> *print-flo-precision*
2> (set *print-flo-precision* 17)
3> (- 1183.68 9.07)
4> 1174.61

You can see that the calculated 1174.61 is not the same number as the
converted from a constant.

Incidentally, 15 is the value of the DBG_DIG constant in C. 15 is the
of decimal digits that the double type is guaranteed to preserve. If you
any 15 digit decimal number (that is in range of double, exponent-wise),
double, then if you convert that double value back to decimal, and round
to 15 digits you will get your original digits.

If we make that 15 the default rounding for general printing of floats,
we get nice looking numbers; but of course, we get a the problem that
aliases to more than one representation, which are not equal, but look
same when printed.

If floating-point, you have to be very careful when you use exact
(e.g. as the condition for terminating a calculation or whatever).

It's possible to have a = function which does the epsilon range check:
numbers are close if they are within some small epsilon value of each
but I think that "dragons be there". Such a thing is no longer an
relation: you will get the problem that (and (= A B) (= B C)) yet
(= A C) is false. There is also the question of what is a good epsilon
to fit
most situations.

Cheers ...