#closeTo: on small numbers

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

#closeTo: on small numbers

Stéphane Rollandin
Hello all,

I just got bitten by the fact that

  1.2246063538223773e-15 closeTo: 3.552713678800501e-15

retuns false.

Now Float>>closeTo: has special tests for zero, so that when a number is
compared to zero the test is based on an absolute deviation.

But in the above case, none of the numbers are actually zero so the
zero-specific test is bypassed, and the regular check based on relative
deviation fails.

I guess this all works as expected. But I am wondering: would #closeTo:
still be consistent if we implemented this way:

closeTo: num
  "are these two numbers close?"
        num isNumber ifFalse: [^[self = num] ifError: [false]].
        self = 0.0 ifTrue: [^num abs < 0.0001].
        num = 0 ifTrue: [^self abs < 0.0001].
        (self closeTo: 0.0) ifTrue: [^self abs < 0.0001].
        ^self = num asFloat
                or: [(self - num) abs / (self abs max: num abs) < 0.0001]


There I added the (self closeTo: 0.0) case to have two near-zero numbers
compared as if one of them was indeed zero.

Would nasty side effects be expected?


Stef

Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Stéphane Rollandin
> (self closeTo: 0.0) ifTrue: [^self abs < 0.0001].

typo: it's
        (self closeTo: 0.0) ifTrue: [^num abs < 0.0001].

Stef

Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Nicolas Cellier
Hi Stephane,
I have unpublished nasty tests showing such kind of weakness of closeTo:

We can use either an absolute precision, or a relative one, but if we try to handle both in same message, we'll get in trouble at the boundaries.
The scheme that might work for comparing x and y is to use prescribed precision as boundary like this:

(xy := x abs max: y abs) > precision
    ifTrue:
        ["use relative precision"
        ^(x-y) abs <= (xy * precision)].
"use absolute precision"
^(x-y) abs <= precision

Le dim. 8 mars 2020 à 11:23, Stéphane Rollandin <[hidden email]> a écrit :
>       (self closeTo: 0.0) ifTrue: [^self abs < 0.0001].

typo: it's
        (self closeTo: 0.0) ifTrue: [^num abs < 0.0001].

Stef



Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Stéphane Rollandin
> We can use either an absolute precision, or a relative one, but if we
> try to handle both in same message, we'll get in trouble at the boundaries

Ok, but considering that the current #closeTo: implementation already
mixes both approaches, is my proposed version an improvement or is it
problematic? Because it does fix my specific problem.

Best,

Stef

Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Nicolas Cellier
Does it pass the two tests that I just published?

Le dim. 8 mars 2020 à 11:37, Stéphane Rollandin <[hidden email]> a écrit :
> We can use either an absolute precision, or a relative one, but if we
> try to handle both in same message, we'll get in trouble at the boundaries

Ok, but considering that the current #closeTo: implementation already
mixes both approaches, is my proposed version an improvement or is it
problematic? Because it does fix my specific problem.

Best,

Stef



Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Stéphane Rollandin
> Does it pass the two tests that I just published?

Yes


Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Nicolas Cellier
Then it's good enough, can you publish/commit in https://source.squeak.org/inbox?

Le dim. 8 mars 2020 à 11:58, Stéphane Rollandin <[hidden email]> a écrit :
> Does it pass the two tests that I just published?

Yes




Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Stéphane Rollandin
> Then it's good enough, can you publish/commit in
> https://source.squeak.org/inbox?

I don't know how this works.

I googled a bit and read the instruction at
http://wiki.squeak.org/squeak/3279 but couldn't make it at step 3 - the
changes I see if I select the Kernel-Numbers package are huge, I don't
see how I can make a mcz with only my method in it.

Could someone provide me *detailed* instructions about what to do?

Stef

Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Stéphane Rollandin
In reply to this post by Nicolas Cellier
> Then it's good enough, can you publish/commit in
> https://source.squeak.org/inbox?

Done

Reply | Threaded
Open this post in threaded view
|

Re: #closeTo: on small numbers

Nicolas Cellier
cool, now in trunk :)

Le dim. 8 mars 2020 à 14:25, Stéphane Rollandin <[hidden email]> a écrit :
> Then it's good enough, can you publish/commit in
> https://source.squeak.org/inbox?

Done