bug comparing floats

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

bug comparing floats

Ted Bracht-3
Evaluate:

659.05+20.9 = 679.95

returns false

((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)

returns true


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Ted Bracht-3
Sorry, this is D5.1.1 Pro (haven't tried in other versions)


"Ted Bracht" <[hidden email]> wrote in message
news:3f4e82a7$[hidden email]...

> Evaluate:
>
> 659.05+20.9 = 679.95
>
> returns false
>
> ((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)
>
> returns true
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Bill Schwab-2
In reply to this post by Ted Bracht-3
Ted,

> Evaluate:
>
> 659.05+20.9 = 679.95
>
> returns false
>
> ((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)
>
> returns true

But look at 659.05+20.9 - 679.95.  Floats are not precise representations,
so a relative error or other range-based test is usually necessary.  Also,
see #asTrueFraction.

There could be a defect at work here, but I doubt it.  I'm acutually more
interested in why the rounded case works :)

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

estow
In reply to this post by Ted Bracht-3
Ted

I think that a little digging through newsgroups will turn up many such
Float and floating point arithmetic "errors" being reported.

All software float objects are an approximation of the mathematical real
number, with the precision of the software float determined by the number
of bytes used to represent the number.

Try inspecting the lhs and rhs of the expression, and (at least in VW ) and
the values assigned to each byte.  Usually the least significant byte value
will be different.

So if you are using Floats to represent a Currency amount - be aware of
these problems.

VW has an ~= message that does answer true,

659.05d  + 20.9d  ~= 679.95d --> true

In VW I have to force the use of double precision floats to reproduce the
anomalie.


On Thu, 28 Aug 2003 23:06:41 +0100, Ted Bracht <[hidden email]>
wrote:

> Sorry, this is D5.1.1 Pro (haven't tried in other versions)
>
>
> "Ted Bracht" <[hidden email]> wrote in message
> news:3f4e82a7$[hidden email]...
>> Evaluate:
>>
>> 659.05+20.9 = 679.95
>>
>> returns false
>>
>> ((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)
>>
>> returns true
>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Louis Sumberg-2
In reply to this post by Ted Bracht-3
Hi Ted,

You might try using #equals:

659.05+20.9 equals: 679.95 returns true.

btw, 659.05+20.9 - 679.95 returns -1.13686837721616e-013
which makes sense as per the other posts on this.  Gotta love them floats,
eh? *ugh*

-- Louis

"Ted Bracht" <[hidden email]> wrote in message
news:3f4e82a7$[hidden email]...

> Evaluate:
>
> 659.05+20.9 = 679.95
>
> returns false
>
> ((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)
>
> returns true
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Blair McGlashan
In reply to this post by Bill Schwab-2
"Bill Schwab" <[hidden email]> wrote in message
news:bim2it$av5iq$[hidden email]...

> Ted,
>
> > Evaluate:
> >
> > 659.05+20.9 = 679.95
> >
> > returns false
> >
> > ((659.05+20.9) roundTo: 0.01) = (679.95 roundTo: 0.01)
> >
> > returns true
>
> But look at 659.05+20.9 - 679.95.  Floats are not precise representations,
> so a relative error or other range-based test is usually necessary.  Also,
> see #asTrueFraction.
>
> There could be a defect at work here, but I doubt it.  I'm acutually more
> interested in why the rounded case works :)
>

I think this should make that clearer:

#(659.05 20.9 679.95 ##(659.05 + 20.9) ##((659.05 + 20.9) roundTo: 0.01))
do: [:each | each printOn: Transcript decimalPlaces: 15. Transcript cr]

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Blair McGlashan
In reply to this post by estow
Edward

You wrote in message news:[hidden email]...
> ...
> VW has an ~= message that does answer true,
>
> 659.05d  + 20.9d  ~= 679.95d --> true
> ...

Careful, the meaning of #~= in Smalltalk is not "approximately equal" as you
might expect, but "not equal". In this it will give the "right" result :-).
AFAIK VW does not provide a method to compare whether to floats are equal to
a specified precision. A handy method for doing so is:

compare: x to: y epsilon: epsilon
    "Compare that the two <Float> values are equivalent to within the
specified <Float> difference."

    | max |
    ^(max := x abs max: y abs) <= epsilon
        or:  [(x - y) abs < (epsilon * max)]

We use this method in our SUnit test hierarchy as it allows one to specify
the maximum "error". It should work correctly regardless of the magnitudes
involved; the naiive implementation '(x - y) < epsilon'  gives the wrong
result for large floats since it takes no account of the precision limits of
the representation. A handy shortcut for this is the #equals: message on
Float, which uses a precision of 1e-9, which is appropriate for many uses.

It would be nice to have a standard binary selector for #equals: in
Smalltalk (and a standard value for the epsilon it uses for single and
double precision floats), but unfortunately the obvious choices using the
'~' character are either in use or likely to be confused with #~= (not
equal) and #~~ (not identical).

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Jochen Riekhof-3
In reply to this post by Ted Bracht-3
There is a nice book covering the whole issue and in addition containig a
lot of nice numerical stuff.

http://www.amazon.com/exec/obidos/tg/detail/-/1558606793/qid=1062160102/sr=8
-1/ref=sr_8_1/002-0279682-7698445?v=glance&s=books&n=507846

It also contains a library that is already ported to Dolphin.
http://sourceforge.net/projects/dhbnumerics/

A Number>>equalsTo: (comparing taking the systems numerical precision into
account) and Number>>relativelyEqualsTo:upTo:  as proposed in this thread is
also included.

Ciao

...Jochen


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

Bill Schwab-2
In reply to this post by Blair McGlashan
Blair,

> > There could be a defect at work here, but I doubt it.  I'm acutually
more
> > interested in why the rounded case works :)
> >
>
> I think this should make that clearer:
>
> #(659.05 20.9 679.95 ##(659.05 + 20.9) ##((659.05 + 20.9) roundTo: 0.01))
> do: [:each | each printOn: Transcript decimalPlaces: 15. Transcript cr]

That does help.  Should this perhaps be the default #printOn:
(developer-specific) for floats??

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: bug comparing floats

estow
In reply to this post by Blair McGlashan
On Fri, 29 Aug 2003 09:47:52 +0100, Blair McGlashan <[hidden email]>
wrote:

> Edward
>
> You wrote in message news:[hidden email]...
>> ...
>> VW has an ~= message that does answer true,
>>
>> 659.05d  + 20.9d  ~= 679.95d --> true
>> ...
>
> Careful, the meaning of #~= in Smalltalk is not "approximately equal" as
> you
> might expect, but "not equal". In this it will give the "right" result :-)
>
>


   Doh

  "Expressing frustration at the realization ...that one has just said or
done something foolish."
   OED  http://dictionary.oed.com/

[Remainder of message snipped]