In the CLHS dictionary entry for EQL it says:
eql may not be true of two floats even when they represent the same
value.
What does "the same value" mean in this context. For instance, is this
saying that (eql 1.0 1.0) may be either true or false? Or just
something like (eql (/ 6.0 2.0) 3.0)?
-Peter
--
Peter Seibel ·····@javamonkey.com
The intellectual level needed for system design is in general
grossly underestimated. I am convinced more than ever that this
type of work is very difficult and that every effort to do it with
other than the best people is doomed to either failure or moderate
success at enormous expense. --Edsger Dijkstra
Peter Seibel <·····@javamonkey.com> writes:
> In the CLHS dictionary entry for EQL it says:
> eql may not be true of two floats even when they represent the same
> value.
> What does "the same value" mean in this context.
From
http://www.lisp.org/HyperSpec/Body/fun_eql.html
I take it to mean that two differently typed floats representing
the same number doesn't compare equal under eql.
> For instance, is this saying that (eql 1.0 1.0) may be either true
> or false?
Always true, I believe. (eql 1.0s0 1.0d0) should be true iff
(eq (type-of 1.0s0) (type-of 1.0d0)).
"Peter Seibel" <·····@javamonkey.com> wrote in message
···················@javamonkey.com...
> In the CLHS dictionary entry for EQL it says:
>
> eql may not be true of two floats even when they represent the same
> value.
>
> What does "the same value" mean in this context. For instance, is this
> saying that (eql 1.0 1.0) may be either true or false? Or just
> something like (eql (/ 6.0 2.0) 3.0)?
>
Here's the deal. 'eql' returns true iff
- the two objects are 'eq'
- or two characters are "the same"
- or two numbers have the same type and same value
Note that two floating point numbers can be numerically equal
without having the same type! (eql 1.0d0 1.0s0) should evaluate
to false on Lisps that support double precision.
Expressions like (eql (/ 6.0 2.0) 3.0) evaluate to false if the floating
point precision of the reader and of the arithmetic operators are
not quite "the same". I'm too lazy to type all the details of this, tho'.
In article <··············@javamonkey.com>, Peter Seibel wrote:
> In the CLHS dictionary entry for EQL it says:
>
> eql may not be true of two floats even when they represent the same
> value.
>
> What does "the same value" mean in this context. For instance, is this
> saying that (eql 1.0 1.0) may be either true or false? Or just
> something like (eql (/ 6.0 2.0) 3.0)?
>
> -Peter
>
It is almost always wrong to compare two floating point numbers
for equality. Your example just happens to work because you divide
by two, unlike the following example:
(eql (- (- 5.11 5.0) 0.11) 0.0)
NIL
This is off cause becuase the floating point unit gives round-off
errors, so (- (- 5.11 5.0) 0.11) don't give exactly 0,
(- (- 5.11 5.0) 0.11)
1.3411045e-7
Equality with floating point numbers should be handled with caution.
This comes in addition to the type issues mentioned by others.
It is difficult to get the same value on both side in floating point
calculations.
--
Gisle S�lensminde
Computational biology unit, University of Bergen, Norway
Email: ·····@cbu.uib.no
Biology easily has 500 years of exciting problems to work on. (Donald Knuth)
Gisle S�lensminde <·····@kaktus.ii.uib.no> writes:
> It is almost always wrong to compare two floating point numbers
> for equality. Your example just happens to work because you divide
> by two, unlike the following example:
>
> (eql (- (- 5.11 5.0) 0.11) 0.0)
> NIL
>
> This is off cause becuase the floating point unit gives round-off
> errors, so (- (- 5.11 5.0) 0.11) don't give exactly 0,
>
> (- (- 5.11 5.0) 0.11)
> 1.3411045e-7
While your example works, there is no floating point round-off error
during the computation. (The error occurs during the READ of the
numbers.) I'm being pedantic, but it's worth understanding.
5.0 is represented, in floating point, as the rational number
10485760/2097152 (exactly equal to 5)
5.11 is represented as
10716447/2097152 (a tad more that 511/100)
subtracting gives exactly
230687/2097152 which is normalized to the exact equivalent
14763968/134217728
so there is no rounding error in this subtraction
.11 is represented as
14763950/134217728 (a tad less than 11/100)
subtracting again gives exactly
18/134217728 which is normalized to
9437184/70368744177664
which is printed as 1.3411045e-7
so there is no rounding error in the second subtraction, either.
All the error occurs at read time when the decimal value is converted
to a float.
Gisle S�lensminde <·····@kaktus.ii.uib.no> writes:
> In article <··············@javamonkey.com>, Peter Seibel wrote:
> > In the CLHS dictionary entry for EQL it says:
> >
> > eql may not be true of two floats even when they represent the
> > same value.
> >
> > What does "the same value" mean in this context. For instance, is this
> > saying that (eql 1.0 1.0) may be either true or false? Or just
> > something like (eql (/ 6.0 2.0) 3.0)?
> >
> > -Peter
> >
>
> It is almost always wrong to compare two floating point numbers
> for equality. Your example just happens to work because you divide
> by two, unlike the following example:
>
> (eql (- (- 5.11 5.0) 0.11) 0.0)
> NIL
>
> This is off cause becuase the floating point unit gives round-off
> errors, so (- (- 5.11 5.0) 0.11) don't give exactly 0,
>
> (- (- 5.11 5.0) 0.11)
> 1.3411045e-7
>
> Equality with floating point numbers should be handled with caution.
> This comes in addition to the type issues mentioned by others. It is
> difficult to get the same value on both side in floating point
> calculations.
Right. I get that. But I wouldn't call 0.0 and 1.3411045e-7 the "same"
value. So I was wondering what it meant for the values to be the
"same" yet not EQL. The case of (eql 1.0s0 1.0d0) ==> false makes
sense; I hadn't thought of that possibility.
-Peter
--
Peter Seibel ·····@javamonkey.com
The intellectual level needed for system design is in general
grossly underestimated. I am convinced more than ever that this
type of work is very difficult and that every effort to do it with
other than the best people is doomed to either failure or moderate
success at enormous expense. --Edsger Dijkstra
In article <··············@javamonkey.com>, Peter Seibel wrote:
> Gisle S�lensminde <·····@kaktus.ii.uib.no> writes:
>
>
> Right. I get that. But I wouldn't call 0.0 and 1.3411045e-7 the "same"
> value. So I was wondering what it meant for the values to be the
> "same" yet not EQL. The case of (eql 1.0s0 1.0d0) ==> false makes
> sense; I hadn't thought of that possibility.
My point was that floating points almost never is the "same" after
a computation, and I guess we agree there, but I just corrected a
colleague's code that was broken exactly for the reason that he used
equality for checking that the results of a computation were the same.
As Joe Marshall pointed out, my example was not an example of
rounding errors, but that floating point numbers don't always represent
the input value exactly.
Floating point are not easy....
--
--
Gisle S�lensminde
Computational biology unit, University of Bergen, Norway
Email: ·····@cbu.uib.no
Biology easily has 500 years of exciting problems to work on. (Donald Knuth)
Gisle S�lensminde <·····@apal.ii.uib.no> writes:
> In article <··············@javamonkey.com>, Peter Seibel wrote:
> > Gisle S�lensminde <·····@kaktus.ii.uib.no> writes:
> >
> >
> > Right. I get that. But I wouldn't call 0.0 and 1.3411045e-7 the "same"
> > value. So I was wondering what it meant for the values to be the
> > "same" yet not EQL. The case of (eql 1.0s0 1.0d0) ==> false makes
> > sense; I hadn't thought of that possibility.
>
> My point was that floating points almost never is the "same" after a
> computation, and I guess we agree there, but I just corrected a
> colleague's code that was broken exactly for the reason that he used
> equality for checking that the results of a computation were the
> same.
>
> As Joe Marshall pointed out, my example was not an example of
> rounding errors, but that floating point numbers don't always
> represent the input value exactly.
>
> Floating point are not easy....
No. They are deep voodoo as far as I'm concerned. Beyond the type
difference problem, an email correspondent pointed out that you can
also have normalization differences: The same value can be represented
as 1 x 2^1 and 2 x 2^0. But the bit-patterns would be different and
EQL isn't obligated to figure out that they are the same value.
Or something. As I said, it's all voodoo to me.
-Peter
--
Peter Seibel ·····@javamonkey.com
The intellectual level needed for system design is in general
grossly underestimated. I am convinced more than ever that this
type of work is very difficult and that every effort to do it with
other than the best people is doomed to either failure or moderate
success at enormous expense. --Edsger Dijkstra
>>>>> "Peter" == Peter Seibel <·····@javamonkey.com> writes:
Peter> No. They are deep voodoo as far as I'm concerned. Beyond the type
Peter> difference problem, an email correspondent pointed out that you can
Peter> also have normalization differences: The same value can be represented
Peter> as 1 x 2^1 and 2 x 2^0. But the bit-patterns would be different and
Peter> EQL isn't obligated to figure out that they are the same value.
Yes, there is a normalization issue, but just about everyone
implements IEEE floating-point arithmetic so all numbers are always
normalized if they are within range. So it's not possible to get 1 x
2^1 and 2 x 2^0. It's always 1 x 2^1.
Ray
> Gisle S�lensminde <·····@apal.ii.uib.no> writes:
> > Floating point are not easy....
Peter Seibel <·····@javamonkey.com> writes:
> No. They are deep voodoo as far as I'm concerned.
They really aren't all that bad. Read a few of the papers on William
Kahan's web site: http://www.cs.berkeley.edu/~wkahan/
The thing to realize is this: floating point numbers are exact
rational numbers. In particular, they are a selected set of exact
rational numbers. In any binary float, the denominator is a power of
2. In single precision, the numerator is an integer between 8388608
and 16777215. In double precision, the numerator is and integer
between 4503599627370496 and 9007199254740991. All the usual rules of
rational arithmetic apply to floating point numbers, except for one:
if the result is not expressible in the floating point format, the
result is rounded to the nearest number that *is* expressible. (And
good floating point hardware has a means to let you know if it needed
to round or not.)