From: Pedro Kroger
Subject: floating-point comparison
Date: 
Message-ID: <1168094491.490913.48990@s34g2000cwa.googlegroups.com>
Is it ok to use = to compare floating point numbers in common lisp? At
least it works for me (with sbcl 1.0):

CL-USER> (= 1.0 1.0000000000000000000000000001)
T

Pedro Kroger

From: Thomas M. Hermann
Subject: Re: floating-point comparison
Date: 
Message-ID: <1168103536.830163.266570@s34g2000cwa.googlegroups.com>
Pedro Kroger wrote:
> Is it ok to use = to compare floating point numbers in common lisp? At
> least it works for me (with sbcl 1.0):
>
> CL-USER> (= 1.0 1.0000000000000000000000000001)
> T

Regardless of the language, it is usually more meaningful to test
whether the difference between two floating point numbers is less than
some epsilon.

(< (abs (- 1.0 1.00000001)) epsilon)

You'll probably want to define some function to perform this. If you
really want to get picky, you'll need to dig into the details of the
hardware representation of floating point numbers, usually IEEE 754 or
854 on modern CPUs. If you get that picky, you should probably be using
C or Fortran.

Cheers,

Tom
From: rjf
Subject: Re: floating-point comparison
Date: 
Message-ID: <1168104751.297241.37880@q40g2000cwq.googlegroups.com>
Thomas M. Hermann wrote:
> Pedro Kroger wrote:
> > Is it ok to use = to compare floating point numbers in common lisp?

Sure, if your experience is that it is OK in other programming
languages.

Some of the previous responders have addressed a different issue raised
by your example, which is how a string of decimal digits is converted
to an internal representation when read into a computer by lisp.

As for whether the answer you get from comparison by "=" is useful or
not, that depends on your goal, and is independent of whether you are
using lisp, C, Fortran, or any other language, and is even independent
of binary, decimal, 32-bit, 64-bit, arbitrary-precision etc. As was
mentioned, comparing floating-point numbers by looking at the relative
or absolute size of their difference is sometimes preferable.

RJF
From: Thomas A. Russ
Subject: Re: floating-point comparison
Date: 
Message-ID: <ymibql9fiin.fsf@sevak.isi.edu>
"rjf" <·······@gmail.com> writes:

> As for whether the answer you get from comparison by "=" is useful or
> not, that depends on your goal, and is independent of whether you are
> using lisp, C, Fortran, or any other language, and is even independent
> of binary, decimal, 32-bit, 64-bit, arbitrary-precision etc. As was
> mentioned, comparing floating-point numbers by looking at the relative
> or absolute size of their difference is sometimes preferable.

And at least Common Lisp provides SOME help in regard to picking useful
and portable epsilon values.  Look at the constants:

SHORT-FLOAT-EPSILON
SHORT-FLOAT-NEGATIVE-EPSILON
SINGLE-FLOAT-EPSILON
SINGLE-FLOAT-NEGATIVE-EPSILON
DOUBLE-FLOAT-EPSILON
DOUBLE-FLOAT-NEGATIVE-EPSILON
LONG-FLOAT-EPSILON
LONG-FLOAT-NEGATIVE-EPSILON



-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: floating-point comparison
Date: 
Message-ID: <87irfk9okw.fsf@thalassa.informatimago.com>
"Pedro Kroger" <············@gmail.com> writes:

> Is it ok to use = to compare floating point numbers in common lisp? At
> least it works for me (with sbcl 1.0):
>
> CL-USER> (= 1.0 1.0000000000000000000000000001)
> T

May work, may not work.


C/USER2[904]> #+clisp (setf (EXT:LONG-FLOAT-DIGITS) 400)
400
C/USER2[905]> (setf *READ-DEFAULT-FLOAT-FORMAT* 'long-float)
LONG-FLOAT
C/USER2[906]> (= 1.0 1.0000000000000000000000000001)
NIL


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: Alan Crowe
Subject: Re: floating-point comparison
Date: 
Message-ID: <86bqlavjy0.fsf@cawtech.freeserve.co.uk>
"Pedro Kroger" <············@gmail.com> writes:

> Is it ok to use = to compare floating point numbers in common lisp? At
> least it works for me (with sbcl 1.0):
> 
> CL-USER> (= 1.0 1.0000000000000000000000000001)
> T

It is reasonable to say

(defun f (x y)
  (if (= x y) (handle special case somehow)
      (/ (- x y))))

but the reason why this is reasonable is subtle.
The point is that the range of floating point numbers is
much greater than their precision. For example double floats
have perhaps 16 digits of precision, but can be as large as
10^308. 

So if x and y are close, they either cancel exactly, or
leave a residue that is are worst 16 decimal digits smaller
than they were. If x and y were not tiny, down at 10^-300
then (/ (- x y)) will not overflow.

Other than this special case (= x y) is an accident waiting
to happen. Once you have chosen to use floats instead of
rationals you have chosen inexact arithmetic and had better
plan on comparing floats to see if they are close in
relation to the accuracy of your calculation.

For example if x is the result of a minimisation of a
function with a roughly quadratic minimum, x will only be
accurate to half the number of digits you worked with. If
you computed to double x will be accurate to about single and
(= x y) will nearly always fail

Alan Crowe
Edinburgh
Scotland