Lisp HUG Maillist Archive

Rational = float

I found a bug in my codes witch was due to a comparison between a fractional
number and a float number. Because the float number is a 'limited' float
with max 2 numbers after the point (and is always rational) I thought it
works because :

(= 1.0 1) => T
(= 0.5 1/2) => T
(= 0.25 1/4) => T
(= 1.125 9/8) => T
Etc.

But in fact

(= 0.2 1/5) => NIL

Is it correct to say that the denominator of the rational must always be a
power of two  to make a valid comparison with a float ?

In addition, is it a operator that return T for the test of comparison of
0.2 and 1/5 ? Or is it the best solution to make (= 0.2 (float 1/5)) ?

Thanks

Denis

-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Rational = float

Unable to parse email body. Email id is 7654

Re: Rational = float

Le 5/02/08 13:55, « [NOM] » <[ADRESSE]> a écrit :

>    [...]
> 
>    But in fact
> 
>    (= 0.2 1/5) => NIL
> 
>    Is it correct to say that the denominator of the rational must
>    always be a power of two to make a valid comparison with a float ?
> 
> This condition is sufficient but might not be necessary.
> 
>    In addition, is it a operator that return T for the test of
>    comparison of 0.2 and 1/5 ? Or is it the best solution to make (=
>    0.2 (float 1/5)) ?
> 
> See the "Rule of Float and Rational Contagion"
> 
> http://www.lispworks.com/documentation/HyperSpec/Body/12_ada.htm

Ah yes, so :

(rational 0.2) => 13421773/67108864 (glup...)

And then (= 13421773/67108864 1/5) => NIL (here I understand something)

And, as says Espen : (rationalize 0.2) => 1/5 (ouf!)

But is not the RATIONALIZE function too expensive in term of performances to
generalize a (rationalize float) mechanism ? Hmmm...

Fortunately, I use float for displaying convenience and not really for
computation. So I thing I could simply avoid this comparison (and it will
certainly be more prudent)

Thanks for your very interesting explanations (and the others I received)

Denis

> 
> The 1/5 is coerced to a float as part of the = operation.
> 
> The real issue is: you should always (in any programming language) be
> extremely wary when comparing floats, which by their very nature can
> never be guaranteed exact. Both 0.2 and (float 1/5) have to be inexact
> as IEEE floats, and it happens that they are inexact differently.
> 
> Something like
> 
>    (defun close-enough-= (this that)
>      (< (abs (- this that))
>         +tolerance+))
> 
> might be more appropriate.
> 
> - nick
> 

-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Rational = float

Denis Pousseur <denis.pousseur@gmail.com> writes:

> And, as says Espen : (rationalize 0.2) => 1/5 (ouf!)
>
> But is not the RATIONALIZE function too expensive in term of performances to
> generalize a (rationalize float) mechanism ? Hmmm...

YMMV. It's not 100% reliable either, at least it will fool you if you
(EEK!) want to work with short-floats:

NFTPD 59 > (rationalize (coerce 95/100 'short-float))
41495/43679

(I don't know if that might possibly be a bug in LWs rationalize
 implementation...?)

but it works fine with all single- and double-floats from 0.01, 0.02,
...., 0.99
-- 
  (espen)


Re: Rational = float

Denis Pousseur <denis.pousseur@gmail.com> writes:

> I found a bug in my codes witch was due to a comparison between a fractional
> number and a float number. Because the float number is a 'limited' float
> with max 2 numbers after the point (and is always rational) I thought it
> works because :

All floating point numbers are rational. They're all
mantissa*base^exponent.

> (= 1.0 1) => T
> (= 0.5 1/2) => T
> (= 0.25 1/4) => T
> (= 1.125 9/8) => T
> Etc.
>
> But in fact
>
> (= 0.2 1/5) => NIL
>
> Is it correct to say that the denominator of the rational must always be a
> power of two  to make a valid comparison with a float ?

A power of two not greater than the number of bits in the mantissa.

> In addition, is it a operator that return T for the test of comparison of
> 0.2 and 1/5 ? Or is it the best solution to make (= 0.2 (float 1/5)) ?

Even that could fail for a number of reasons. 

If you're going to work with floating point numbers, read Goldberg's
"What every computer scientist should know about floating point
arithmetic". It's easy available on the internet.

-- 
For a student of mathematics to hear someone talk about mathematics does 
hardly any more good than for a student of swimming to hear someone talk
about swimming.                                            - Paul Halmos


Re: Rational = float



Le 5/02/08 14:04, « [NOM] » <[ADRESSE]> a écrit :

> 
> Denis Pousseur <denis.pousseur@gmail.com> writes:
> 
>> I found a bug in my codes witch was due to a comparison between a fractional
>> number and a float number. Because the float number is a 'limited' float
>> with max 2 numbers after the point (and is always rational) I thought it
>> works because :
> 
> All floating point numbers are rational. They're all
> mantissa*base^exponent.
> 
>> (= 1.0 1) => T
>> (= 0.5 1/2) => T
>> (= 0.25 1/4) => T
>> (= 1.125 9/8) => T
>> Etc.
>> 
>> But in fact
>> 
>> (= 0.2 1/5) => NIL
>> 
>> Is it correct to say that the denominator of the rational must always be a
>> power of two  to make a valid comparison with a float ?
> 
> A power of two not greater than the number of bits in the mantissa.

Could we consider then that (=  1.0 1) return *always* T ?

Thanks

Denis

> 
>> In addition, is it a operator that return T for the test of comparison of
>> 0.2 and 1/5 ? Or is it the best solution to make (= 0.2 (float 1/5)) ?
> 
> Even that could fail for a number of reasons.
> 
> If you're going to work with floating point numbers, read Goldberg's
> "What every computer scientist should know about floating point
> arithmetic". It's easy available on the internet.

-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Rational = float

Denis Pousseur <denis.pousseur@gmail.com> writes:

> In addition, is it a operator that return T for the test of comparison of
> 0.2 and 1/5 ? Or is it the best solution to make (= 0.2 (float 1/5)) ?

I think (= (rationalize 0.2) 1/5) will work for your usage.
-- 
  (espen)


Updated at: 2020-12-10 08:44 UTC