Mantis - Squeak
Viewing Issue Advanced Details
7368 Kernel minor always 07-14-09 07:06 04-18-10 22:05
nicolas cellier  
nicolas cellier  
normal  
closed 3.10.2  
fixed  
none    
none trunk  
0007368: 1.0 closeTo: 200 factorial
self deny: (1.0 closeTo: 200 factorial).

(1.0 closeTo: 100 factorial) is false as expected.
(1 closeTo: 200 factorial) is also false as expected.

See also 0006729
The trick for doing a fuzzy compare will trigger a coercion of the huge integer to Float infinity.

    fuzz := (self abs max: num abs) * 0.0001.

Then comparison will just lead to Float infinity <= Float infinity which happens to be true, thanks to IEEE754 weird rules (See 0006729 )

    ^ (self - num) abs <= fuzz

A protection against infinity has been placed above, but it does not apply because (200 factorial isFinite).

    self isInfinite == num isInfinite ifFalse: [^ false].
 M7368-closeTo-Patch-nice.1.cs [^] (611 bytes) 07-14-09 07:35
 M7368-closeTo-Test-nice.1.cs [^] (992 bytes) 07-14-09 07:36
 M7368-closeTo-Patch-nice.2.cs [^] (427 bytes) 07-16-09 23:01
 M7368-closeTo-Patch-nice.3.cs [^] (345 bytes) 07-16-09 23:07
 M7368-closeTo-Test-nice.2.cs [^] (1,844 bytes) 07-19-09 17:32
 M7368-closeTo-Patch-nice.4.cs [^] (599 bytes) 07-19-09 17:32

Notes
(0013186)
nicolas cellier   
07-14-09 07:17   
For the fun of it, please note:

(1.0 closeTo: 200 factorial) -> true.
(200 factorial closeTo: 1.0) -> false.

You can also play with:

{
Float infinity closeTo: 200 factorial.
200 factorial closeTo: Float infinity.
}.

I wish you good luck before you find an implementation passing all these tricks :)
(0013187)
nicolas cellier   
07-14-09 07:37   
"fix begin"
Installer mantis bug: 7368 fix:'M7368-closeTo-Patch-nice.1.cs'.
"fix test"
Installer mantis bug: 7368 fix:'M7368-closeTo-Test-nice.1.cs'.
"fix end"
(0013188)
nicolas cellier   
07-14-09 07:39   
I gave it a try.
These tests and patch supersedes 0006729.

In this implementation, (FloatInfinity closeTo: 200 factorial) will be true.
(0013196)
bonzini   
07-16-09 06:13   
Alternatively, this is also good:

        "Needed to return true for +Inf/+Inf and -Inf/-Inf"
        self = num ifTrue: [^true].
        ^(self - num) abs / (self abs max: num abs) <= 0.0001

If one is finite and the other is not, the final comparison becomes NaN / NaN <= 0.0001 which is always false.
(0013197)
nicolas cellier   
07-16-09 19:29   
Yes, sounds simpler, Inf/Inf -> Nan.
If 0003374 is applied though, we should write
        self = num asFloat ifTrue: [^true].
because
        Float infinity noLongerEqual: 200 factorial.

(0013198)
nicolas cellier   
07-16-09 23:06   
M7368-closeTo-Patch-nice.2.cs (forgot to remove = 0 tests)
and M7368-closeTo-Patch-nice.3.cs are a lot simpler thanks to Paolo
closeTo: num
     "are these two numbers close?"
    num isNumber ifFalse: [^[self = num] ifError: [false]].
    ^self = num asFloat
        or: [(self - num) abs / (self abs max: num abs) < 0.0001]

Note that I changed <= 0.0001 into < 0.0001.
This in case 0007260 is not already applied in your favourite squeak VM
(0013203)
nicolas cellier   
07-19-09 11:46   
"fix begin"
Installer mantis bug: 7368 fix:'M7368-closeTo-Patch-nice.3.cs'.
"fix test"
Installer mantis bug: 7368 fix:'M7368-closeTo-Test-nice.1.cs'.
"fix end"
(0013204)
nicolas cellier   
07-19-09 17:33   
Hmm not enough tests written... :(
The = 0 tests were necessary of course.
(0013205)
nicolas cellier   
07-19-09 17:33   
"fix begin"
Installer mantis bug: 7368 fix:'M7368-closeTo-Patch-nice.4.cs'.
"fix test"
Installer mantis bug: 7368 fix:'M7368-closeTo-Test-nice.2.cs'.
"fix end"
(0013273)
nicolas cellier   
08-24-09 20:10   
Fixed in http://source.squeak.org/trunk/Kernel-nice.193.mcz [^]