Issue 940: (13/10) = 1.3 returns false

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

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
2009/7/7 Hernan Wilkinson <[hidden email]>:

> ok, but can you be sure that your objects are not handling floats? maybe the
> same code handles floats when you want speed and fractions when you want
> precision, I remember we did that once but I don't remember if we had to
> compare the numbers...
> I understand your point and I agree with you that erratic behavior should be
> avoided as much as possible, new programmers always get confused when two
> floats print the same but return false when compared, but do you agree with
> me that this new behavior make floats "less polymorphic" with numbers? and
> code more odd?... you see, people will have the same question as me, why
> (13/10) = 1.3 returns false but (1/2) = 0.5 returns true?
> Maybe the solution has to be more drastic, and if we want to avoid people
> for comparing floats for equality, just not let them or return false
> always... or take the other road as Smalltalk had after now, that is: make
> the implementation detail as hide as possible, and if the programmer really
> cares about representation problems let him compare the numbers with a
> difference...
> Smalltalk has almost 30 years old and I have not seen any big problem
> related to comparing numbers, so why changing that? what do we gain with the
> change?... I'm still not sure that this change is for the better :-)
>
>

Well, we are going to lack of arguments and just repeat ourselves :)
It is for the better because it makes comparison a full order relation
ship and equality transitive.

| a b c |
a := 13/10.
b := a asFloat.
c := b asTrueFraction.
a < c
self asssert: (a = b) & (b = c) ==> (a == c).
self asssert: (a < c) & (b = c) ==> (a < b).

It is also better because your learn sooner to not be surpised by
1.3*1.3 ~= 1.69.

You should know that lispers (lots of grey bearded) were better
behaved than us, long before us.
See http://www.lispworks.com/documentation/lcl50/aug/aug-170.html
That's not a definitive argument, but a good clue.

Concerning (1/2) ~= 0.5, Andres suggested that once, why not. This is
explicitely possible to implement Scheme with this rule.

I gave you some examples that are not hypothetical: I've been caught
15 years ago with this kind of bad behaviour.
I now would like to see real examples rather than just expectations
based on bad habits.

Nicolas

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Stéphane Ducasse
2009/7/7 Stéphane Ducasse <[hidden email]>:

>
> On Jul 7, 2009, at 11:21 PM, Hernan Wilkinson wrote:
>
>> ok, but can you be sure that your objects are not handling floats?
>> maybe the same code handles floats when you want speed and fractions
>> when you want precision, I remember we did that once but I don't
>> remember if we had to compare the numbers...
>> I understand your point and I agree with you that erratic behavior
>> should be avoided as much as possible, new programmers always get
>> confused when two floats print the same but return false when
>> compared, but do you agree with me that this new behavior make
>> floats "less polymorphic" with numbers? and code more odd?... you
>> see, people will have the same question as me, why (13/10) = 1.3
>> returns false but (1/2) = 0.5 returns true?
>> Maybe the solution has to be more drastic, and if we want to avoid
>> people for comparing floats for equality, just not let them or
>> return false always... or take the other road as Smalltalk had after
>> now, that is: make the implementation detail as hide as possible,
>> and if the programmer really cares about representation problems let
>> him compare the numbers with a difference...
>> Smalltalk has almost 30 years old and I have not seen any big
>> problem related to comparing numbers, so why changing that? what do
>> we gain with the change?... I'm still not sure that this change is
>> for the better :-)
>
> :-)
> yes I understand that point too :)
> So please continue to discuss that we understand the deep pros and
> cons. I think this is extremely healthy
>
> Stef
>

Except the polymorphism argument, this is more a principle of inertia.
"Why did you change the browser, I want it back..."

IMO, Smalltalk had not so many problems because it is not used for
number crunching.
Financial apps use ScaledDecimal where due and avoid the problem.
I used it for crunching numbers, but I feel a bit alone :)

Concerning polymorphism, I hope I demonstrated this is a false
polymorphism because you get non transitive equality and numbers not
well ordered.

Anyway:
| a b |
a = 13/10.
b= a asFloat.
self assert: (a = b) ==> (a squared = b squared).
self assert: (a = b) ==> (a fractionPart = b fractionPart).
etc...
They behave differently, really.

Concerning (0.5) ~= (1/2) that might be a good idea.
What stopped me was the implications it would have on inequality tests...
0.5 < (1/2). -> false
0.5 = (1/2). -> false
0.5 > (1/2). -> false
So they are unordered... I prefer 0.5 = (1/2). -> true strategy mainly
for this reason.

Nicolas

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Andres Valloud-4
On the other hand, asRational and asFraction are quite synonym to me.
asFraction might as well be implementation dependent...
And asRational can be interpreted this way only for historical reasons (st80).
I want either a short approximated fraction like (13/10), or an exact fraction.

Nicolas

2009/7/8 Andres Valloud <[hidden email]>:

> On the other hand, VW already has asRational, and it doesn't do what
> asFraction does.  To some extent, I think #asExactFraction and selectors
> like that are misleading.  Why would anyone want #asImpreciseFraction,
> or #asRationalMoreOrLess...
>
> Nicolas Cellier wrote:
>> Hi Andres,
>> That's great to see this addition, but it would have been even greater
>> to call this method #asExactFraction or #asTrueFraction to get some
>> minimal core API with other dialects...
>>
>> Anyway, you see the kind of arguments you'll have to provide if you
>> ever want to follow the path you once proposed...
>>
>> Cheers
>>
>> Nicolas
>>
>> 2009/7/7 Andres Valloud <[hidden email]>:
>>
>>> VisualWorks introduced LimitedPrecisionReal>>asFraction.  That message
>>> returns the actual floating point value represented by the receiver.  Of
>>> course, I messed up and forgot * self sign... but that's the idea (and
>>> it's fixed for 7.7).  So, in reality, you should compare
>>>
>>> 13/10 = 1.3 asFraction
>>>
>>> which will answer false, like it should.
>>>
>>> Andres.
>>>
>>>
>>> John M McIntosh wrote:
>>>
>>>> Let me step back and say, ok you are possibly breaking existing code,
>>>> and causing all sorts of confusion for an
>>>> optimization change?  So where is the justification from the
>>>> optimization viewpoint? Does it make browser
>>>> windows open in 1/2 the time?
>>>>
>>>> If it takes more time milliseconds? to produce an answer that is what
>>>> people expect, then t I think it's worth it.
>>>> Yes I understand that floats are inexact but people think they know
>>>> how they work thus expect to be able to say
>>>> (13/10) = 1.3   without having to give clues with asFloat to indicate
>>>> their intent.
>>>>
>>>> Let me see
>>>> squeak 3.10.x   (13/10) = 1.3   true
>>>> Pharo 1037  (13/10) = 1.3   false
>>>> VisualWorks (13/10) = 1.3   true
>>>>
>>>> I would classify this as a bug
>>>>
>>>>
>>>> On 7-Jul-09, at 10:43 AM, Hernan Wilkinson wrote:
>>>>
>>>>
>>>>
>>>>> I added this new issue that happens on the latest image.
>>>>> I'm posting it here because I think it is an important bug because
>>>>> it affects the number model.
>>>>> The problem is related with all fractions who's denominator is not
>>>>> power of two. (130/100 = 1.3 or 1/5 = 0.2, etc)
>>>>> (See
>>>>> Float>>adaptToFraction: rcvr andCompare: selector where it does
>>>>>    ....
>>>>>    "Try to avoid asTrueFraction because it can cost"
>>>>>     selector == #= ifTrue: [
>>>>>       rcvr denominator isPowerOfTwo ifFalse: [^false]].
>>>>>
>>>>>    ...)
>>>>>
>>>>>
>>>>> Hernan.
>>>>>
>>>>>
>>>> --
>>>> =
>>>> =
>>>> =
>>>> ========================================================================
>>>> John M. McIntosh <[hidden email]>   Twitter:
>>>> squeaker68882
>>>> Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
>>>> =
>>>> =
>>>> =
>>>> ========================================================================
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Pharo-project mailing list
>>>> [hidden email]
>>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>>
>>>>
>>>>
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [hidden email]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>
>>>
>> .
>>
>>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Andres Valloud-4
2009/7/8 Andres Valloud <[hidden email]>:
> The answer is true on 7.6, and I don't think anything changed that for
> 7.7.  Historical background aside, I think it's wrong anyway... in the
> hash book, exercise 7.20 asks to find two different fractions that are
> equal to the same float.  In other words, if f is a float, and r1 and r2
> are fractions, then r1 ~= r2 but r1 = f and r2 = f.  And those do exist...
>
> Andres.
>

Il y a même une infinité de Fractions r telles que
f-0.5*ulp < r < f+0.5ulp

Anyway, Andres, tell me what how you can bear this VW behaviour I
exposed to Michael L.S.

9.9999730e20 printString -> '1.0e21'
9.9999731e20 printString -> '9.99997e20'
9.9999731e20 >= 9.9999730e20. false

To me, this is a clear violation of ISO/IEC 10967-2
http://www.cs.chalmers.se/~kent/ISOStandards/SC22/WG11/LIA-2/N424.ps
I guess "we Smalltalk guys are smarter and did not change things for
30 years, so why bother now" is our best argument :)

Nicolas

>
> Stéphane Ducasse wrote:
>> so andres what will be the value of
>>
>>>> (13/10) = 1.3
>>>>
>> in VW7.7
>>
>> On Jul 7, 2009, at 11:18 PM, Andres Valloud wrote:
>>
>>
>>> VisualWorks introduced LimitedPrecisionReal>>asFraction.  That message
>>> returns the actual floating point value represented by the
>>> receiver.  Of
>>> course, I messed up and forgot * self sign... but that's the idea (and
>>> it's fixed for 7.7).  So, in reality, you should compare
>>>
>>> 13/10 = 1.3 asFraction
>>>
>>> which will answer false, like it should.
>>>
>>> Andres.
>>>
>>>
>>> John M McIntosh wrote:
>>>
>>>> Let me step back and say, ok you are possibly breaking existing code,
>>>> and causing all sorts of confusion for an
>>>> optimization change?  So where is the justification from the
>>>> optimization viewpoint? Does it make browser
>>>> windows open in 1/2 the time?
>>>>
>>>> If it takes more time milliseconds? to produce an answer that is what
>>>> people expect, then t I think it's worth it.
>>>> Yes I understand that floats are inexact but people think they know
>>>> how they work thus expect to be able to say
>>>> (13/10) = 1.3   without having to give clues with asFloat to indicate
>>>> their intent.
>>>>
>>>> Let me see
>>>> squeak 3.10.x   (13/10) = 1.3   true
>>>> Pharo 1037  (13/10) = 1.3   false
>>>> VisualWorks (13/10) = 1.3   true
>>>>
>>>> I would classify this as a bug
>>>>
>>>>
>>>> On 7-Jul-09, at 10:43 AM, Hernan Wilkinson wrote:
>>>>
>>>>
>>>>
>>>>> I added this new issue that happens on the latest image.
>>>>> I'm posting it here because I think it is an important bug because
>>>>> it affects the number model.
>>>>> The problem is related with all fractions who's denominator is not
>>>>> power of two. (130/100 = 1.3 or 1/5 = 0.2, etc)
>>>>> (See
>>>>> Float>>adaptToFraction: rcvr andCompare: selector where it does
>>>>>   ....
>>>>>   "Try to avoid asTrueFraction because it can cost"
>>>>>    selector == #= ifTrue: [
>>>>>      rcvr denominator isPowerOfTwo ifFalse: [^false]].
>>>>>
>>>>>   ...)
>>>>>
>>>>>
>>>>> Hernan.
>>>>>
>>>>>
>>>> --
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =====================================================================
>>>> John M. McIntosh <[hidden email]>   Twitter:
>>>> squeaker68882
>>>> Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =
>>>> =====================================================================
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Pharo-project mailing list
>>>> [hidden email]
>>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>>
>>>>
>>>>
>>> _______________________________________________
>>> Pharo-project mailing list
>>> [hidden email]
>>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>>
>>
>> .
>>
>>
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

johnmci
In reply to this post by Nicolas Cellier

On 7-Jul-09, at 2:46 PM, Nicolas Cellier wrote:
> I repeat here my arguments:
> Anyone depending on (13/10) = 1.3 is plain wrong...


Historically and as far as I can tell in all other versions of  
smalltalk (13/10) = 1.3   why be different?
If you *want* exact then I suggest you have (13/10)  
asAInexactFloatExactlyEquals: 1.3     and let who wants that type of  
compare live with it.

As for real world examples.

http://www.mobilewikiserver.com/Fraction.html

has 104 test cases, unluckily the the math ones didn't trigger a  
failure but the calculator keyboard entry engine did

" Test to enter .1 in memory storage, then confirm retrieval works"

        self tap: '.'.
        self tap: 1.
        self tap: 'S'.
        self should: [self enteredData = '.1'].
        self should: [self storedEntry = 0.1].

because
(1/10) = 0.1  => false

Sometimes what is false can be true because well people do think 1/10  
= 0.1


--
=
=
=
========================================================================
John M. McIntosh <[hidden email]>   Twitter:  
squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
=
=
=
========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Michael van der Gulik-2
In reply to this post by hernan.wilkinson


2009/7/8 Hernan Wilkinson <[hidden email]>
I added this new issue that happens on the latest image.
I'm posting it here because I think it is an important bug because it affects the number model.
The problem is related with all fractions who's denominator is not power of two. (130/100 = 1.3 or 1/5 = 0.2, etc)
(See
Float>>adaptToFraction: rcvr andCompare: selector where it does
....
"Try to avoid asTrueFraction because it can cost"
selector == #= ifTrue: [
rcvr denominator isPowerOfTwo ifFalse: [^false]].
...)


A hypothetical question: would it be harmful if the compiler stored number literals as Fractions rather than Floats? For example, the compiler could store "1.3" as the literal "13/10" in the CompiledMethod. The denominator would always be a multiple of 10 or whatever the base of the specified number is.

Gulik.


--
http://gulik.pbwiki.com/

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Igor Stasenko
In reply to this post by Nicolas Cellier
2009/7/8 Nicolas Cellier <[hidden email]>:

> 2009/7/7 John M McIntosh <[hidden email]>:
>> Let me step back and say, ok you are possibly breaking existing code,
>> and causing all sorts of confusion for an
>> optimization change?  So where is the justification from the
>> optimization viewpoint? Does it make browser
>> windows open in 1/2 the time?
>>
>> If it takes more time milliseconds? to produce an answer that is what
>> people expect, then t I think it's worth it.
>> Yes I understand that floats are inexact but people think they know
>> how they work thus expect to be able to say
>> (13/10) = 1.3   without having to give clues with asFloat to indicate
>> their intent.
>>
>> Let me see
>> squeak 3.10.x   (13/10) = 1.3   true
>> Pharo 1037  (13/10) = 1.3   false
>> VisualWorks (13/10) = 1.3   true
>>
>> I would classify this as a bug
>>
>>
>
> I repeat here my arguments:
> Anyone depending on (13/10) = 1.3 is plain wrong...
>
+1.
I dealt with 3D rendering/linear algebra using floats in the past ,
and i can say just one:
- never write the code which compares the floats to be equal to some
exact value.
It makes no sense in practice, because of inexact nature of floats.
For instance, i remember the code i wrote, to test whether two vectors
perpendicular:
float := n1 * n2   (where n1 , n2 - is line normals, and * - is dot product).

As we know, if two vectors is perpendicular, then their dot product is zero.
But it is almost always non-zero on hardware, especially when you
transform vectors or compute them using data, which already contains a
degree of precision error!
So, i learned that comparing dot product with zero makes no sense,
instead you'd better test it with something like:

abs(float) < epsilon
where epsilon is very small number.

So, i don't understand, why its so important for such kind of equality
tests to work right at all - because you hardly will use such tests in
practice.

> Either you want fast and inexact floating point operation and should
> not rely on exact equality (use #closeTo:).
> Or you want (13/10) = 1.3 EXACTLY, and then should better use ScaledDecimal.
> That's the deal, and it's quite independant from the language.
>
> The false assertions that people are trying to push does not matter:
> it's high time to educate.
> My proposition has at least the merit to put a light on these
> dangerous floating point strict equality tests
> (I saw so many bugs like testing cos(pi/2) == 0).
>
> And I'm still waiting for the hypothetical application that would
> break because of this change.
> That's the main point of interest.
> In this case, we'll see if patching is necessary and easy.
>
> Nicolas
>
> P.S. concerning behaviour of conversion binary<->decimal
> representation, I'm rather the one trying to unify Smalltalk.
> Dolphin, gst and Pharo adopted some of my changes to behave as exactly
> as we can, and thus behave the same.
> Try this in your prefered dialect, I guess you will have some surprise.
> 123.4567890123d3 = (1234567890123/10000000).
> 123.4567890123d3 = (1234567890123/10000000) asFloat.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>



--
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Michael van der Gulik-2
2009/7/8 Michael van der Gulik <[hidden email]>:

>
>
> 2009/7/8 Hernan Wilkinson <[hidden email]>
>>
>> I added this new issue that happens on the latest image.
>> I'm posting it here because I think it is an important bug because it
>> affects the number model.
>> The problem is related with all fractions who's denominator is not power
>> of two. (130/100 = 1.3 or 1/5 = 0.2, etc)
>> (See
>>
>> Float>>adaptToFraction: rcvr andCompare: selector where it does
>>    ....
>>    "Try to avoid asTrueFraction because it can cost"
>>     selector == #= ifTrue: [
>> rcvr denominator isPowerOfTwo ifFalse: [^false]].
>>
>>
>>    ...)
>>
>
> A hypothetical question: would it be harmful if the compiler stored number
> literals as Fractions rather than Floats? For example, the compiler could
> store "1.3" as the literal "13/10" in the CompiledMethod. The denominator
> would always be a multiple of 10 or whatever the base of the specified
> number is.
>
> Gulik.
>
>

Well this already exists and is named ScaledDecimal...


> --
> http://gulik.pbwiki.com/
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Igor Stasenko
As a compromise,
i propose adding:

Float>>isAlmostZero
  ^ self abs < Epsilon


And write tests like:

(13/10) = 1.3

in form:

((13/10) - 1.3) isAlmostZero

--
Best regards,
Igor Stasenko AKA sig.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
2009/7/8 Igor Stasenko <[hidden email]>:

> As a compromise,
> i propose adding:
>
> Float>>isAlmostZero
>  ^ self abs < Epsilon
>
>
> And write tests like:
>
> (13/10) = 1.3
>
> in form:
>
> ((13/10) - 1.3) isAlmostZero
>

Yes, there is already #closeTo: with an arbitrary tolerance (absolute
or relative, depending if an operand isZero) and some weird side
effects:
1.0 closeTo: (10 raisedTo: 310).
-> true

> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Andres Valloud-4
In reply to this post by Nicolas Cellier

> Il y a même une infinité de Fractions r telles que
> f-0.5*ulp < r < f+0.5ulp
>
>  

Yes... find two with small integer numerators and denominators... bonus
points if you find fractions with small smallIntegers, too.

> Anyway, Andres, tell me what how you can bear this VW behaviour I
> exposed to Michael L.S.
>
> 9.9999730e20 printString -> '1.0e21'
> 9.9999731e20 printString -> '9.99997e20'
> 9.9999731e20 >= 9.9999730e20. false
>
> To me, this is a clear violation of ISO/IEC 10967-2
> http://www.cs.chalmers.se/~kent/ISOStandards/SC22/WG11/LIA-2/N424.ps
> I guess "we Smalltalk guys are smarter and did not change things for
> 30 years, so why bother now" is our best argument :)
>  

I don't know what the deal is with that.  However, I am not surprised
that relying on print strings for floating point numbers leads to bogus
results.

On a more positive note, according to our current plans, VW 7.7 will
provide vastly improved IEEE arithmetic including proper support for INF
and NaN.

Andres.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Andres Valloud-4
In reply to this post by Igor Stasenko
The VW tests use something along the lines of

self assert: aResult isWithin: anInteger ulpsFrom: anExpectedValue

Igor Stasenko wrote:

> As a compromise,
> i propose adding:
>
> Float>>isAlmostZero
>   ^ self abs < Epsilon
>
>
> And write tests like:
>
> (13/10) = 1.3
>
> in form:
>
> ((13/10) - 1.3) isAlmostZero
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>  

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Ignacio Vivona-2
In school teachers told me that 13/10 = 1.3, applications that handle money believe the same (at least the ones that i worked on) and then we have to use some other implementation of numbers because the 3d guys (i also coded some 3d stuff in C) and the speed guys want the default numbers to be fast and inaccurate. Why not the opposite? If you want speed and you are willing to sacrifices presition then use the implementation alternative.

On Tue, Jul 7, 2009 at 9:43 PM, Andres Valloud <[hidden email]> wrote:
The VW tests use something along the lines of

self assert: aResult isWithin: anInteger ulpsFrom: anExpectedValue

Igor Stasenko wrote:
> As a compromise,
> i propose adding:
>
> Float>>isAlmostZero
>   ^ self abs < Epsilon
>
>
> And write tests like:
>
> (13/10) = 1.3
>
> in form:
>
> ((13/10) - 1.3) isAlmostZero
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project



--
Hope is for sissies (Gregory House, M.D.)

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Andres Valloud-4
2009/7/8 Andres Valloud <[hidden email]>:

>
>> Il y a même une infinité de Fractions r telles que
>> f-0.5*ulp < r < f+0.5ulp
>>
>>
>
> Yes... find two with small integer numerators and denominators... bonus
> points if you find fractions with small smallIntegers, too.
>
>> Anyway, Andres, tell me what how you can bear this VW behaviour I
>> exposed to Michael L.S.
>>
>> 9.9999730e20 printString -> '1.0e21'
>> 9.9999731e20 printString -> '9.99997e20'
>> 9.9999731e20 >= 9.9999730e20. false
>>
>> To me, this is a clear violation of ISO/IEC 10967-2
>> http://www.cs.chalmers.se/~kent/ISOStandards/SC22/WG11/LIA-2/N424.ps
>> I guess "we Smalltalk guys are smarter and did not change things for
>> 30 years, so why bother now" is our best argument :)
>>
>
> I don't know what the deal is with that.  However, I am not surprised
> that relying on print strings for floating point numbers leads to bogus
> results.
>

I was trying to attack printString based on (log: 10) rounding error,
but that is not the main problem.
The main problem is 9.9999731e20 < 9.9999730e20: decimal->binary
conversion is not monotonic.

> On a more positive note, according to our current plans, VW 7.7 will
> provide vastly improved IEEE arithmetic including proper support for INF
> and NaN.
>
> Andres.
>

That's good news.
Concerning NaN and Inf, I wonder if really a great idea. This
introduces all sort of complexifications in the image.

The main point of exceptional values is to avoid interrupting FP
computations and rather introduce sparse tests at strategic points in
code. It must be viewed as an optimization.
Knowing that Smalltalk has all sort of overhead on FP computations, I
wonder if adding a isFinite test in primitives at each operation and
raising an Exception immediately rather than differed at chosen points
was not a better compromise....

I guess the clients decide anyway...

Will FP exceptions be programmable?

> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Nicolas Cellier
In reply to this post by Ignacio Vivona-2
Ignacio, not sure your bank handle money with inexact floating point
arithmetic...
ScaledDecimal are made for that.
When they want to "round" your account, they have more efficient rules
(like the one named 'Frais Bancaires' in France).
Such rules are more predictable and rarely with fractions but rather
integer numbers of €, always negative ;)

This apart, I personnally did not choose to sacrifice anything. Your
hardware did this well before I put my hands on a keyboard.
I think you mis-understand the point.
I'm waiting the answer why 1.3*1.3 is different from 169/100. When
you'll have discovered this, we'll talk about 13/10 = 1.3 on more
serious bases.

Nicolas

2009/7/8 Ignacio Vivona <[hidden email]>:

> In school teachers told me that 13/10 = 1.3, applications that handle money
> believe the same (at least the ones that i worked on) and then we have to
> use some other implementation of numbers because the 3d guys (i also coded
> some 3d stuff in C) and the speed guys want the default numbers to be fast
> and inaccurate. Why not the opposite? If you want speed and you are willing
> to sacrifices presition then use the implementation alternative.
>
> On Tue, Jul 7, 2009 at 9:43 PM, Andres Valloud
> <[hidden email]> wrote:
>>
>> The VW tests use something along the lines of
>>
>> self assert: aResult isWithin: anInteger ulpsFrom: anExpectedValue
>>
>> Igor Stasenko wrote:
>> > As a compromise,
>> > i propose adding:
>> >
>> > Float>>isAlmostZero
>> >   ^ self abs < Epsilon
>> >
>> >
>> > And write tests like:
>> >
>> > (13/10) = 1.3
>> >
>> > in form:
>> >
>> > ((13/10) - 1.3) isAlmostZero
>> >
>> > --
>> > Best regards,
>> > Igor Stasenko AKA sig.
>> >
>> > _______________________________________________
>> > Pharo-project mailing list
>> > [hidden email]
>> > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>> >
>> >
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
>
> --
> Hope is for sissies (Gregory House, M.D.)
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Andres Valloud-4
In reply to this post by Nicolas Cellier

>> On a more positive note, according to our current plans, VW 7.7 will
>> provide vastly improved IEEE arithmetic including proper support for INF
>> and NaN.
>>
>> Andres.
>>
>>    
>
> That's good news.
> Concerning NaN and Inf, I wonder if really a great idea. This
> introduces all sort of complexifications in the image.
>
>  

I don't know... I wouldn't call 7.7's state complex, given what you're
getting.  But... I guess you'll have to be the judge of that when it
comes out :).

> The main point of exceptional values is to avoid interrupting FP
> computations and rather introduce sparse tests at strategic points in
> code. It must be viewed as an optimization.
> Knowing that Smalltalk has all sort of overhead on FP computations, I
> wonder if adding a isFinite test in primitives at each operation and
> raising an Exception immediately rather than differed at chosen points
> was not a better compromise....
>  

In VW, you can choose between FP primitives that fail before answering
INF or NaN, or primitives that will give you whatever the FPU says.  
This decision can be made at runtime.  The default is the legacy
behavior of prims that fail before answering INF or NaN.

Andres.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

Andres Valloud-4
In reply to this post by Nicolas Cellier

Nicolas Cellier wrote:
> Ignacio, not sure your bank handle money with inexact floating point
> arithmetic...
>  

Note that it depends on the application... if pricing is inexact, then
being off by $0.01 is fine.

The big issue is the confusion between "1.3" as a floating point value,
and "1.3" as the scaled decimal value.

Andres.

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

johnmci
In reply to this post by Nicolas Cellier

On 7-Jul-09, at 6:40 PM, Nicolas Cellier wrote:

> I'm waiting the answer why 1.3*1.3 is different from 169/100. When
> you'll have discovered this, we'll talk about 13/10 = 1.3 on more
> serious bases.
>
> Nicolas

Well for Fraction I do  (1.3*1.3 ) asApproximateFraction  (169/100)
because people have expectations about (1.3*1.3) = 169/100
the same expectations they likely had for (1/10) = 0.1

noting that
(1/10) = 0.1 false
(1/10) = (0.1 asApproximateFraction) true


Personally I think here the issue is more what the different smalltalk  
think and do for various float to faction conversions
not perhaps what is correct. Unless of course you want to drop any  
numerical compatibility?

--
=
=
=
========================================================================
John M. McIntosh <[hidden email]>   Twitter:  
squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
=
=
=
========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

johnmci
In reply to this post by johnmci

On 7-Jul-09, at 4:09 PM, John M McIntosh wrote:

> self should: [self storedEntry = 0.1].
>
> because
> (1/10) = 0.1  => false

I should note the test is slightly wrong because storedEntry is a  
fraction and I should be testing for 1/10
and somewhere in the 100 or so other tests I'm check for issues with  
float to fraction conversions.
Where as mentioned in a later note I  use asApproximateFraction in the  
proper places to avoid
conversion errors.

--
=
=
=
========================================================================
John M. McIntosh <[hidden email]>   Twitter:  
squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
=
=
=
========================================================================





_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Reply | Threaded
Open this post in threaded view
|

Re: Issue 940: (13/10) = 1.3 returns false

hernan.wilkinson
In reply to this post by Nicolas Cellier
ok, let me start again.
1) I created the issue because 13/10 = 1.3 works different in the new pharo image that in vw, va, dolphin, squeak and the previous pharo version, so I thought it was a bug
2) I understand that comparing floats is not good and I also understand the representation problems of floats
3) I'm in favor of making changes. Changes are needed to make progress although not all changes make progress 

But, Nicolas when you say
> Anyone depending on (13/10) = 1.3 is plain wrong...
I do not completely agree. You say that because you are thinking like a programmer and you know that 1.3 is a float, but if you ask the same question to an accountant, engineering, etc. they will say that 13/10 is equal to 1.3. So, outside computers, 13/10 is equal to 1.3, the same as 1/2 equals to 0.5 and so on.
Dan Ingalls followed a good design principle: to hide as much as possible implementation details from the user and that is why Smalltalk has such a great Number model that I did not see in another language.
From my point of view, the implementation you are providing is not quite following this principle or at least is making the float representation problem more evident. If the last is the intention, I think it should be consistent (i.e. 1/2 = 0.5 should return false also) and provide specific messages to handle that decision too.
Or maybe the change has to be more profound, maybe changes like the one suggested by Michael van der Gulik 
are necessary, maybe we have to print ScaledDecimals as float are printed now and print floats with a special representation to make evident that is not a "normal" number... 

Anyway, as I said before, I'm not sure this change is a good decision, time will tell I guess, those are my two cents. 
Bye,
Hernan




On Tue, Jul 7, 2009 at 7:37 PM, Nicolas Cellier <[hidden email]> wrote:
2009/7/7 Stéphane Ducasse <[hidden email]>:
>
> On Jul 7, 2009, at 11:21 PM, Hernan Wilkinson wrote:
>
>> ok, but can you be sure that your objects are not handling floats?
>> maybe the same code handles floats when you want speed and fractions
>> when you want precision, I remember we did that once but I don't
>> remember if we had to compare the numbers...
>> I understand your point and I agree with you that erratic behavior
>> should be avoided as much as possible, new programmers always get
>> confused when two floats print the same but return false when
>> compared, but do you agree with me that this new behavior make
>> floats "less polymorphic" with numbers? and code more odd?... you
>> see, people will have the same question as me, why (13/10) = 1.3
>> returns false but (1/2) = 0.5 returns true?
>> Maybe the solution has to be more drastic, and if we want to avoid
>> people for comparing floats for equality, just not let them or
>> return false always... or take the other road as Smalltalk had after
>> now, that is: make the implementation detail as hide as possible,
>> and if the programmer really cares about representation problems let
>> him compare the numbers with a difference...
>> Smalltalk has almost 30 years old and I have not seen any big
>> problem related to comparing numbers, so why changing that? what do
>> we gain with the change?... I'm still not sure that this change is
>> for the better :-)
>
> :-)
> yes I understand that point too :)
> So please continue to discuss that we understand the deep pros and
> cons. I think this is extremely healthy
>
> Stef
>

Except the polymorphism argument, this is more a principle of inertia.
"Why did you change the browser, I want it back..."

IMO, Smalltalk had not so many problems because it is not used for
number crunching.
Financial apps use ScaledDecimal where due and avoid the problem.
I used it for crunching numbers, but I feel a bit alone :)

Concerning polymorphism, I hope I demonstrated this is a false
polymorphism because you get non transitive equality and numbers not
well ordered.

Anyway:
| a b |
a = 13/10.
b= a asFloat.
self assert: (a = b) ==> (a squared = b squared).
self assert: (a = b) ==> (a fractionPart = b fractionPart).
etc...
They behave differently, really.

Concerning (0.5) ~= (1/2) that might be a good idea.
What stopped me was the implications it would have on inequality tests...
0.5 < (1/2). -> false
0.5 = (1/2). -> false
0.5 > (1/2). -> false
So they are unordered... I prefer 0.5 = (1/2). -> true strategy mainly
for this reason.

Nicolas

_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


_______________________________________________
Pharo-project mailing list
[hidden email]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
12345