[Pharo-project] Issue 940: (13/10) = 1.3 returns false
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.
Hi Hernan, This is the new Behavior of Float comparison and it is desired. 1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52' Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000' As you can see, this is quite different from 13/10. However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true. 2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice. 3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374 So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality... Cheers. Nicolas 2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Oh, just something I forgot to mention: ScaledDecimal should behave the way you expect. 1.3s1 = (13/10). -> true. 1.3s2*1.3s2 = 1.69s2. -> true 1.3 * 1.3 = 1.69. -> false Nicolas 2009/7/7 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Hi Nicolas, thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much... On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Why not the opposite? The default behavior is 13/10 = 1.3 yields true and the new behavior (13/10) asFloat = 1.3 equals false. This kind of behavior is a real pain in languages like java, i are you bringing this to the smalltalk world? 2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>
Hi Nicolas, thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
2009/7/7 Ignacio Vivona <altobarba@gmail.com>:
Why not the opposite? The default behavior is 13/10 = 1.3 yields true and the new behavior (13/10) asFloat = 1.3 equals false. This kind of behavior is a real pain in languages like java, i are you bringing this to the smalltalk world?
Hi Ignacio. If you'd provide a rationale for the behaviour you're proposing we could argue. Otherwise my answer would just be speculation. If 1.3 is 13/10 explain why 1.3*1.3 is not 169/100. As I told before, you should better use ScaledDecimals if you rely on such assertions. Cheers Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>
Hi Nicolas, Â thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Â Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
The float problem is an implementation problem that i really dont care, i only want fast float operations when doing heavy calculation or 3D or something like that ... 1.3 should gimme an object modeling a real number On Tue, Jul 7, 2009 at 5:26 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2009/7/7 Ignacio Vivona <altobarba@gmail.com>:
Why not the opposite? The default behavior is 13/10 = 1.3 yields true and the new behavior (13/10) asFloat = 1.3 equals false. This kind of behavior is a real pain in languages like java, i are you bringing this to the smalltalk world?
Hi Ignacio. If you'd provide a rationale for the behaviour you're proposing we could argue. Otherwise my answer would just be speculation.
If 1.3 is 13/10 explain why 1.3*1.3 is not 169/100.
As I told before, you should better use ScaledDecimals if you rely on such assertions.
Cheers
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>
Hi Nicolas, thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me...
I
mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). ->
'10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
2009/7/7 Ignacio Vivona <altobarba@gmail.com>:
The float problem is an implementation problem that i really dont care, i only want fast float operations when doing heavy calculation or 3D or something like that ... 1.3 should gimme an object modeling a real number
OK concerning fast, that's not the main talent of Squeak, but yes, it could be worse with ScaledDecimals. OK, an object modelling a real number, inexactly, is what you get, so i do not see the problem. Float representation is independant of the language and most likely hardwired in your processor. Whether it is exactly equal to (13/10) or not is an implementation detail you should not bother with... ... until you try to attempt an exact equality test, but why would you? Because you know the tradeoff is fast but inexact, you will rather use something like (13/10) closeTo: 1.3, or better, provide your own tolerance. If you say you expect (13/10) = 1.3 exactly, then i say your expectations are different: you want an exact representation, at the price of longer computations, that's the deal. The fact that Smalltalk let you the choose is already a great thing. Last time I tried (13/10) == 1.3 in C, it was false :) Nicolas
IMO no one should rely on (13/10) = 1.3, not even on (13/10) asFloat = 1.3. Once you introduced a Float, you'd better forget about exact equality. Do you expect 1.3*1.3 ~= 1.69 ? I think it's better like this, because you learn to not overtrust Float equality. You learn quicker that you should not rely on it. However if you give me real examples where this behaviour matters, my ears and eyes are wide open. cheers Nicolas P.S. there is an even more extreme solution: (1/2) ~= 0.5 because an exact and an inexact representation cannot be compared exactly. 2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
Hi Nicolas, Â thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Â Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). -> '10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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 :-) On Tue, Jul 7, 2009 at 5:18 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
IMO no one should rely on (13/10) = 1.3, not even on (13/10) asFloat = 1.3. Once you introduced a Float, you'd better forget about exact equality.
Do you expect 1.3*1.3 ~= 1.69 ? I think it's better like this, because you learn to not overtrust Float equality. You learn quicker that you should not rely on it.
However if you give me real examples where this behaviour matters, my ears and eyes are wide open.
cheers
Nicolas
P.S. there is an even more extreme solution: (1/2) ~= 0.5 because an exact and an inexact representation cannot be compared exactly.
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
Hi Nicolas, thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3 exponent - Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). ->
'10100110011001100110011001100110011001100110011001101/10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game. Floating point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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
On Tue, Jul 7, 2009 at 5:18 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com
wrote: IMO no one should rely on (13/10) = 1.3, not even on (13/10) asFloat = 1.3. Once you introduced a Float, you'd better forget about exact equality.
Do you expect 1.3*1.3 ~= 1.69 ? I think it's better like this, because you learn to not overtrust Float equality. You learn quicker that you should not rely on it.
However if you give me real examples where this behaviour matters, my ears and eyes are wide open.
cheers
Nicolas
P.S. there is an even more extreme solution: (1/2) ~= 0.5 because an exact and an inexact representation cannot be compared exactly.
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
Hi Nicolas, thank you for your answer. I'm aware of the float representation problems. But this new behavior sounds more confusing, at least to me... I mean, 1.3 is not a number with representation problems so why do we have to make this difference? I understand you are trying to avoid the problems sometimes floats generate, but I think that doing so we are loosing some abstraction from the number representation type. Correct me if I wrong, but doesn't this new behavior means that always, in any number comparison, we need to coerse the number to float? Because 1.3 asFraction = (13/10) returns false but 1.3 = (13/10) asFloat returns true... I mean, if we have a = b and the values of those variables are calculated by some process such that a is 1.3 and b is 13/10, the comparison will not work, so we need to explicitly write "a asFloat = b asFloat" just in case any of those variables reference a float, even though none of them will ever do... but then "(1/2) = 0.5" returns true... I don't know, I don't like it that much...
On Tue, Jul 7, 2009 at 3:56 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Hernan, This is the new Behavior of Float comparison and it is desired.
1) 1.3 is represented in machine as (1.3 significandAsInteger printStringRadix: 2) , '.0e' , (1.3
exponent
- Float precision + 1) printString. -> '2r10100110011001100110011001100110011001100110011001101.0e-52'
Or if you prefer: (1.3 asTrueFraction numerator printStringBase: 2) , '/' , (1.3 asTrueFraction denominator printStringBase: 2). ->
'10100110011001100110011001100110011001100110011001101 /10000000000000000000000000000000000000000000000000000'
As you can see, this is quite different from 13/10.
However, you can test (13/10) asFloat = 1.3 and that happens to be true, but that won't always be true.
2) comparing Float with strict equality is a dangerous game.
Floating
point operation are inherently inexact and thus asserting an exact equality is considered a bad practice.
3) basing comparisons and equality tests on inexact arithmetic rather than on exact arithmetic leads to weird behaviours. See http://bugs.squeak.org/view.php?id=3374
So i do not consider this fragment of code alone as a bug but as a feature. There might be some code depending on the old behaviour that can eventually break. If you have such an example in true application, I'm interested. I think we'd better fix such code to not rely on exact equality...
Cheers.
Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/7 Stéphane Ducasse <stephane.ducasse@inria.fr>:
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
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 < nicolas.cellier.aka.nice@gmail.com> wrote:
2009/7/7 Stéphane Ducasse <stephane.ducasse@inria.fr>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
I like Groovy: 1.3 == 13/10 -> true 1.3*1.3 == 169/100 -> true 0.1 == 1/10 -> true 9.9999731e20 < 9.9999730e20 -> false 0.5 == 1/2 -> true 2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>
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 < nicolas.cellier.aka.nice@gmail.com> wrote:
2009/7/7 Stéphane Ducasse <stephane.ducasse@inria.fr>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
In the end, perhaps the issue is: * When users see 1.3, they think decimal floating point. * When programmers see 1.3, they should think binary floating point, but would like to assume decimal floating point. At the end of the day, insisting on seeing 1.3 as decimal floating point runs contrary to what the hardware is doing (I don't know what Groovy's implementation is). This should not be an issue of liking or not liking because we don't get to rewrite or reinterpret the IEEE-754 standard to match our preferences. Ignacio Vivona wrote:
I like Groovy: 1.3 == 13/10 -> true 1.3*1.3 == 169/100 -> true 0.1 == 1/10 -> true 9.9999731e20 < 9.9999730e20 -> false 0.5 == 1/2 -> true
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com <mailto:hernan.wilkinson@gmail.com>>
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 <nicolas.cellier.aka.nice@gmail.com <mailto:nicolas.cellier.aka.nice@gmail.com>> wrote:
2009/7/7 Stéphane Ducasse <stephane.ducasse@inria.fr <mailto:stephane.ducasse@inria.fr>>: > > 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 Pharo-project@lists.gforge.inria.fr <mailto:Pharo-project@lists.gforge.inria.fr> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr <mailto:Pharo-project@lists.gforge.inria.fr> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
Well, I happen to program, but my base job is engineer. And I want my engineers to be aware of such problem and not rely on (cos(pi/2)==0).
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.
On the other hand, it confuses users and then abuse them. This is because the implementation is not neutral but strongly influence the behavior. Every one expects (13/10)=1.3, but the fact is that is not true, these are two different numbers. Try (1.3) fractionPart = (13/10) fractionPart asFloat in Pharo VW Squeak etc... Pretending they are the same is fragile. The model cracks quite fast.
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.
Yes but you then have (0.5,1/2) unordered and probably break more code. Current implementation is a compromise that reflects that these numbers can casually have equal representation. We'd better not lie about what the hardware really does.
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...
Well, Newspeak wanted to follow that route and use ScaledDecimal in first place. But then there are speed tradeoffs... Unfortunately, the stream of money has vanished before we get experimental results...
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
That's true that this is an important change of the semantic of equality. It's reasonnable to doubt, and I thank you for raising the subject, this was necessary. Your opinion is as valuable as mine: inexact equality leads to a simpler model for the user, least surprising because hiding gorry details. I prefer a better mathematical model (= transitive etc...) and to advertise soon about dangers of Float. I say other communities have this behaviour for long (lisp scheme) and it's worth a try . It is also very easy to revert anyway, just replace adaptToXXX:andCompare: with adaptToXXX:andSend:. I have given enough arguments and should let other people express their opinion without fearing an agressive response :) Nicolas
I have given enough arguments and should let other people express their opinion without fearing an agressive response :)
In my opinion the behavior should exactly match the underlying binary representation of floats, otherwise I get results where I feel the system is 'fuzzing' while I didn't tell it to do so and I start to feel uneasy. So where VisualWorks does (13/10) = 1.3 "true" it makes me cringe, OTOH where it does 1.3 = 1.3d "false" it makes me feel right at home. At the heart of the matter is that we use /decimal/ floating point notation to represent /binary/ floats, and the issues (surprises for some people) of approximation should be put at exactly that conversion place and not compensated elsewhere -- this way we get a system with the least surprises. I am too new at Squeak to know how well separated #displayString (application behavior) and #printString (tools behavior) are, but it might help if the tools clearly show when the #printString of a float is approximate by prepending a ~ for example: 1.3 printString "~1.3" 1.0 printString "1.0" Regarding #asExactFraction I'd say that is an ugly pleonasm but more importantly it is confusing (it suggests that #asFraction is fuzzing), hence it should be deprecated; #asFraction should do an exact conversion IMO. R -
I have the impression that we see the problem of representation of what we manipulate. In the mathematical world it makes sense to write 1.3 to mean 13/10 now since in computer world 1.3 is not 13/10 may be we should have ~1.3 or something like that. Stef
exactly! and programing languages should help us not hardware. On Wed, Jul 8, 2009 at 7:03 AM, Stéphane Ducasse <stephane.ducasse@inria.fr>wrote:
I have the impression that we see the problem of representation of what we manipulate. In the mathematical world it makes sense to write 1.3 to mean 13/10 now since in computer world 1.3 is not 13/10 may be we should have ~1.3 or something like that.
Stef
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
What do we mean when we write 1.3 in a computer language, most of the time? Again, looking at VW just because I'm most familiar with it these days, doubles (what Squeak calls floats) are written as 1.3d. Floats (single precision IEEE-754) are written 1.3, but can also be written 1.3e. Hernan Wilkinson wrote:
exactly! and programing languages should help us not hardware.
On Wed, Jul 8, 2009 at 7:03 AM, Stéphane Ducasse <stephane.ducasse@inria.fr <mailto:stephane.ducasse@inria.fr>> wrote:
I have the impression that we see the problem of representation of what we manipulate. In the mathematical world it makes sense to write 1.3 to mean 13/10 now since in computer world 1.3 is not 13/10 may be we should have ~1.3 or something like that.
Stef
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr <mailto:Pharo-project@lists.gforge.inria.fr> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Hi Nicolas, when you say "We'd better not lie about what the hardware really does." does it mean that if the hardware changes the behavior of the program changes too? if that is true, I'm a bit concern about that. I understand your point and it is a good one, but I still disagree with you in something. You say that 13/10 is a different number than 1.3, and as I said, that is true if you think in programing (representation) terms. For me (and that is what I've been taught), 13/10 and 1.3 are different symbols that represent the same number. It is like expresing 3 in roman numbers, III. They are not different numbers but the same written with different symbols. So, I would like my programing language to be aware of this because most of the programers do not have such a good skill on numbers as you do, and I think programing language should be closer to people than to hardware. Andres made a good point too, I think the solution goes that way... Maybe this is a crazy idea and breaks more code as you say, but maybe Float should not be on the Number hierarchy, and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float... and all operations are made with exact representation. And, if you need performance, well, switch to another hierarchy, to one that you explicitly select, that means that you are aware of its limitations. On Wed, Jul 8, 2009 at 12:08 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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.
Well, I happen to program, but my base job is engineer. And I want my engineers to be aware of such problem and not rely on (cos(pi/2)==0).
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.
On the other hand, it confuses users and then abuse them. This is because the implementation is not neutral but strongly influence the behavior. Every one expects (13/10)=1.3, but the fact is that is not true, these are two different numbers. Try (1.3) fractionPart = (13/10) fractionPart asFloat in Pharo VW Squeak etc... Pretending they are the same is fragile. The model cracks quite fast.
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.
Yes but you then have (0.5,1/2) unordered and probably break more code. Current implementation is a compromise that reflects that these numbers can casually have equal representation. We'd better not lie about what the hardware really does.
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...
Well, Newspeak wanted to follow that route and use ScaledDecimal in first place. But then there are speed tradeoffs... Unfortunately, the stream of money has vanished before we get experimental results...
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
That's true that this is an important change of the semantic of equality. It's reasonnable to doubt, and I thank you for raising the subject, this was necessary.
Your opinion is as valuable as mine: inexact equality leads to a simpler model for the user, least surprising because hiding gorry details. I prefer a better mathematical model (= transitive etc...) and to advertise soon about dangers of Float.
I say other communities have this behaviour for long (lisp scheme) and it's worth a try . It is also very easy to revert anyway, just replace adaptToXXX:andCompare: with adaptToXXX:andSend:.
I have given enough arguments and should let other people express their opinion without fearing an agressive response :)
Nicolas
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Fortunately, there's a standard for floating point arithmetic... hopefully we'll get hardware support for decimal floating point some day --- although I can see how somebody might complain because 12765275237652375367328763862.34876387628726872368276823 got rounded to 12765275237652375000000000000... Hernan Wilkinson wrote:
Hi Nicolas, when you say "We'd better not lie about what the hardware really does." does it mean that if the hardware changes the behavior of the program changes too? if that is true, I'm a bit concern about that. I understand your point and it is a good one, but I still disagree with you in something. You say that 13/10 is a different number than 1.3, and as I said, that is true if you think in programing (representation) terms. For me (and that is what I've been taught), 13/10 and 1.3 are different symbols that represent the same number. It is like expresing 3 in roman numbers, III. They are not different numbers but the same written with different symbols. So, I would like my programing language to be aware of this because most of the programers do not have such a good skill on numbers as you do, and I think programing language should be closer to people than to hardware. Andres made a good point too, I think the solution goes that way... Maybe this is a crazy idea and breaks more code as you say, but maybe Float should not be on the Number hierarchy, and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float... and all operations are made with exact representation. And, if you need performance, well, switch to another hierarchy, to one that you explicitly select, that means that you are aware of its limitations.
On Wed, Jul 8, 2009 at 12:08 AM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com <mailto:nicolas.cellier.aka.nice@gmail.com>> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com <mailto:hernan.wilkinson@gmail.com>>: > 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.
Well, I happen to program, but my base job is engineer. And I want my engineers to be aware of such problem and not rely on (cos(pi/2)==0).
> 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.
On the other hand, it confuses users and then abuse them. This is because the implementation is not neutral but strongly influence the behavior. Every one expects (13/10)=1.3, but the fact is that is not true, these are two different numbers. Try (1.3) fractionPart = (13/10) fractionPart asFloat in Pharo VW Squeak etc... Pretending they are the same is fragile. The model cracks quite fast.
> 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.
Yes but you then have (0.5,1/2) unordered and probably break more code. Current implementation is a compromise that reflects that these numbers can casually have equal representation. We'd better not lie about what the hardware really does.
> 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...
Well, Newspeak wanted to follow that route and use ScaledDecimal in first place. But then there are speed tradeoffs... Unfortunately, the stream of money has vanished before we get experimental results...
> 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 >
That's true that this is an important change of the semantic of equality. It's reasonnable to doubt, and I thank you for raising the subject, this was necessary.
Your opinion is as valuable as mine: inexact equality leads to a simpler model for the user, least surprising because hiding gorry details. I prefer a better mathematical model (= transitive etc...) and to advertise soon about dangers of Float.
I say other communities have this behaviour for long (lisp scheme) and it's worth a try . It is also very easy to revert anyway, just replace adaptToXXX:andCompare: with adaptToXXX:andSend:.
I have given enough arguments and should let other people express their opinion without fearing an agressive response :)
Nicolas
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr <mailto:Pharo-project@lists.gforge.inria.fr> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Jul 8, 2009, at 1:31 PM, Hernan Wilkinson wrote:
So, I would like my programing language to be aware of this because most of the programers do not have such a good skill on numbers as you do, and I think programing language should be closer to people than to hardware.
As a counterexample: we readily accept that precedence rules in smalltalk are different than in mathematical notation, 1 + 2 * 3 is interpreted differently in the two notations. So IMO we should lean towards writing programming syntax, not shoe- horning mathematical expectations in there too much. (Mainly because trying to impose mathematical notation will give wrinkling and ripping in all kinds of unexpected places in the system).
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations). R -
Yes. I have the impression that the representation should give the indication of the fuzzyness of the numbers. Now it would be nice that we are of a kind of fix point around this nice discussion :) From what I heard I would like to give a try to the solution proposed by nicolas and also see if we could improve the user experience. I should reread my scheme Stef
On Jul 8, 2009, at 1:31 PM, Hernan Wilkinson wrote:
So, I would like my programing language to be aware of this because most of the programers do not have such a good skill on numbers as you do, and I think programing language should be closer to people than to hardware.
As a counterexample: we readily accept that precedence rules in smalltalk are different than in mathematical notation, 1 + 2 * 3 is interpreted differently in the two notations.
So IMO we should lean towards writing programming syntax, not shoe- horning mathematical expectations in there too much. (Mainly because trying to impose mathematical notation will give wrinkling and ripping in all kinds of unexpected places in the system).
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber ^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc Fraction>>cos ^ numerator cosDividedWith: denominator Pi>>cosDividedWith: denominator ^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ] and so on
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
 ^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
 ^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
 ^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
don't forget to add Pi>>mantisOfLength: numBits to compute the Pi up to given precision. :) But your examples is not about computing a result, but rather predicting it. So why bother writing so much stuff , while you can just implement : Number>>cosPiHalved ^ 0 :)
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
it was just an example where you can "bind" as "late" as possible a combination of symbols with its value... I like late binding :-) in this example allows you to get rigth results... and of course cosPiHalved is not the same as "a/b cos" where a is bound to pi and b to 2... it is not only for literals. On Wed, Jul 8, 2009 at 3:59 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt",
but
for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
don't forget to add Pi>>mantisOfLength: numBits
to compute the Pi up to given precision. :)
But your examples is not about computing a result, but rather predicting it. So why bother writing so much stuff , while you can just implement :
Number>>cosPiHalved ^ 0
:)
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
it was just an example where you can "bind" as "late" as possible a combination of symbols with its value... I like late binding :-) in this example allows you to get rigth results... and of course cosPiHalved is not the same as "a/b cos" where a is bound to pi and b to 2... it is not only for literals.
If you like the late binding, and if you are using a set of functions which having no side effects , then you can, instead of computing the result , store the numerical operations (in same fashion as Fraction stores division) and compute the exact value(s) only when you really need them. Then you can bring in the power of mathematical apparatus/trigonometry rules and use them at full scale. Think, how many things we can add (in parallel to Fraction) SquaredNumber SquaredRootNumber CosFn SinFn TanFn PiFraction and so on.. limited only by your own limits/knowledge... But again, all of this stuff is more related to predicting than exact computing , which is happens to be inexact because of hardware limitations :)
On Wed, Jul 8, 2009 at 3:59 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
 ^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
 ^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
 ^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
don't forget to add Pi>>mantisOfLength: numBits
to compute the Pi up to given precision. :)
But your examples is not about computing a result, but rather predicting it. So why bother writing so much stuff , while you can just implement :
Number>>cosPiHalved  ^ 0
:)
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
The question is why do you want Floats to be the default implementation of reals instead of ScaledDecimals? On Wed, Jul 8, 2009 at 4:29 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
it was just an example where you can "bind" as "late" as possible a combination of symbols with its value... I like late binding :-) in this example allows you to get rigth results... and of course cosPiHalved is not the same as "a/b cos" where a is bound to pi and b to 2... it is not only for literals.
If you like the late binding, and if you are using a set of functions which having no side effects , then you can, instead of computing the result , store the numerical operations (in same fashion as Fraction stores division) and compute the exact value(s) only when you really need them. Then you can bring in the power of mathematical apparatus/trigonometry rules and use them at full scale.
Think, how many things we can add (in parallel to Fraction) SquaredNumber SquaredRootNumber CosFn SinFn TanFn PiFraction and so on.. limited only by your own limits/knowledge...
But again, all of this stuff is more related to predicting than exact computing , which is happens to be inexact because of hardware limitations :)
On Wed, Jul 8, 2009 at 3:59 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root,
log,
sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
don't forget to add Pi>>mantisOfLength: numBits
to compute the Pi up to given precision. :)
But your examples is not about computing a result, but rather predicting it. So why bother writing so much stuff , while you can just implement :
Number>>cosPiHalved ^ 0
:)
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
2009/7/8 Ignacio Vivona <altobarba@gmail.com>:
The question is why do you want Floats to be the default implementation of reals instead of ScaledDecimals?
Ignacio, This is a good question, and I don't have the answer. It would be worth experimenting. Newspeak project wanted to follow this road AFAIK, unfortunately they died before they did it, so we won't benefit from their work... Michael proposed this earlier in the thread. Unfortunately, current ScaledDecimal implementations will reserve more surprises like 0.5s1 * 0.5s1 -> 0.3s1 We should better have the number of decimal digits undefined 0.5s*0.5s -> 0.25s But still limit number of printed characters 1.0s / 3.0s -> 0.3333333s.... Or maybe use a special notation for repeated pattern 1.0s / 3.0s -> 0.3333333(3) 1.0s / 7.0s -> 0.(142857)
On Wed, Jul 8, 2009 at 4:29 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
it was just an example where you can "bind" as "late" as possible a combination of symbols with its value... I like late binding :-) in this example allows you to get rigth results... and of course cosPiHalved is not the same as "a/b cos" where a is bound to pi and b to 2... it is not only for literals.
If you like the late binding, and if you are using a set of functions which having no side effects , then you can, instead of computing the result , store the numerical operations (in same fashion as Fraction stores division) and compute the exact value(s) only when you really need them. Then you can bring in the power of mathematical apparatus/trigonometry rules and use them at full scale.
Think, how many things we can add (in parallel to Fraction) SquaredNumber SquaredRootNumber CosFn SinFn TanFn PiFraction and so on.. limited only by your own limits/knowledge...
But again, all of this stuff is more related to predicting than exact computing , which is happens to be inexact because of hardware limitations :)
On Wed, Jul 8, 2009 at 3:59 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
[...] and if you write 1.3, the object that represents that number is not going to be an instance of float but of scaledecimal or fraction or whatever, but not float...
That only solves the issue of representing literals because:
and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
 ^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
 ^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
 ^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
don't forget to add Pi>>mantisOfLength: numBits
to compute the Pi up to given precision. :)
But your examples is not about computing a result, but rather predicting it. So why bother writing so much stuff , while you can just implement :
Number>>cosPiHalved  ^ 0
:)
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
This kind of approach will introduce discontinuity problems when the FPU is asked to calculate sin(x) when x is close to zero... IME, most platforms offer a different answer to that kind of stuff. IIRC, SGI was the only platform I found with "natural" tan(x) behavior. If you introduce "better" behavior, then the work somebody else did to ensure smoothness of results could be broken. Then, people will ask "why does my algorithm give result x when written in C, but y when written in Squeak?". Hernan Wilkinson wrote:
> [...] and if you write 1.3, the object that represents that number > is not going to be an instance of float but of scaledecimal or > fraction or whatever, but not float...
That only solves the issue of representing literals because:
> and all operations are made with exact representation.
cannot be done for all operations: obvious ones like square root, log, sin, etc and less obvious ones like #squared where you run out of enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
^ Fraction numerator: self denominator: aNumber "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr <mailto:Pharo-project@lists.gforge.inria.fr> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
 Then, people will ask "why does my algorithm give result x when written in C, but y when written in Squeak?".
It happens already... :-)
Hernan Wilkinson wrote:
  > [...] and if you write 1.3, the object that represents that number   > is not going to be an instance of float but of scaledecimal or   > fraction or whatever, but not float...
  That only solves the issue of representing literals because:
  > and all operations are made with exact representation.
  cannot be done for all operations: obvious ones like square root, log,   sin, etc and less obvious ones like #squared where you run out of   enough bits to maintain precision (in fixed-width implementations).
not really... root, log, sin, etc could be messages that only inexact numbers know how to answer , so you want "2 sqrt", Â do "2 asFloat sqrt", but for +, *, /, etc. they work as expected. We can also have better representations for number like pi. Why pi is instance of Float and not Pi? If pi is instance of Pi, then cos(pi/2) = 0 could be true... just a quick hack: Pi>>/ aNumber
 ^ Fraction numerator: self denominator: aNumber  "Or maybe an object representing that Pi has been divided/multiplied, etc
Fraction>>cos
 ^ numerator cosDividedWith: denominator
Pi>>cosDividedWith: denominator
 ^denominator = 2 ifTrue: [ 0 ] ifFalse: [ ... ]
and so on
  R   -
  _______________________________________________   Pharo-project mailing list   Pharo-project@lists.gforge.inria.fr   <mailto:Pharo-project@lists.gforge.inria.fr>   http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Jul 8, 2009, at 4:07 AM, Hernan Wilkinson wrote:
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...
May be this would be good in fact. I was wondering why we could not have = comparison always been false? Stef
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 <nicolas.cellier.aka.nice@gmail.com
wrote: 2009/7/7 Stéphane Ducasse <stephane.ducasse@inria.fr>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/8 Stéphane Ducasse <stephane.ducasse@inria.fr>:
On Jul 8, 2009, at 4:07 AM, Hernan Wilkinson wrote:
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...
May be this would be good in fact.
I was wondering why we could not have     = comparison always been false?
Stef
{(1/2) < 0.5. (1/2) = 0.5. (1/2) > 0.5.}. -> {false. false. false.} We cannot order these two numbers. Well, this will break some other expectations... Like (a >= b) = (a < b) not... IMO, we would be shifting the model from inexact Floating point to Interval arithmetic. Again, this is a possibility, but I'd rather see this Behaviour in a separate class, and let user select his own model. IMO we must provide traditional Floating point arithmetic reflecting the state of the art. Nicolas
2009/7/7 Hernan Wilkinson <hernan.wilkinson@gmail.com>:
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
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = = = = =====================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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. 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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = = = = =====================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
.
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
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 <johnmci@smalltalkconsulting.com> Â Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. Â http://www.smalltalkconsulting.com = = = = = = =====================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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.
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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.
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 <avalloud@smalltalk.comcastbiz.net>:
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 <johnmci@smalltalkconsulting.com> Â Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. Â http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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 <avalloud@smalltalk.comcastbiz.net>:
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
.
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 <avalloud@smalltalk.comcastbiz.net>:
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 <avalloud@smalltalk.comcastbiz.net>:
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 <johnmci@smalltalkconsulting.com> Â Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. Â http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Hi John, There is some misunderstanding here. It just happens that I proposed an optimized implementation, but optimizing was not my goal. My goal was to be able to compare number exactly, that's all. See http://bugs.squeak.org/view.php?id=3374 for funny examples of what happens when comparison is based on inexact conversions. Nicolas 2009/7/7 John M McIntosh <johnmci@smalltalkconsulting.com>:
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 <johnmci@smalltalkconsulting.com> Â Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. Â http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/7 John M McIntosh <johnmci@smalltalkconsulting.com>:
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... 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.
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
2009/7/8 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
2009/7/7 John M McIntosh <johnmci@smalltalkconsulting.com>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
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.
+1 me too Code like '(13/10) = 1.3' just jumps at you if you have been bitten by this before. In languages of APL branch (which are traditionally used for intensive calculations) the comparison of real numbers is 'tolerant': that is two numbers are considered equal if their relative difference is less than some predefined small value: a = b isTrue if: |a-b|/max(a,b) < Epsilon http://www.jsoftware.com/help/primer/tolerance.htm http://jsoftware.com/help/dictionary/d000.htm Creators of these languages put a lot of considiration into this and it I think they got it right. It may be too radical to redefine comparison of real values in Smalltalk (although it still makes sense to do so in practical terms) but the discussed test is just a blind shot into a sky. The user should be discouraged to rely on a such comparison. regards, Danil
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2009/7/8 danil osipchuk <danil.osipchuk@gmail.com>:
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.
+1 me too Code like '(13/10) = 1.3' just jumps at you if you have been bitten by this before. In languages of APL Â branch (which are traditionally used for intensive calculations) the comparison of real numbers is 'tolerant': that is two numbers are considered equal if their relative difference is less than some predefined small value: Â a = b isTrue if: Â |a-b|/max(a,b) < Epsilon
Sorry, I can't help talking :) Of course, this model does not preserve good properties like = being transitive. a := 1.0 - (0.5*Epsilon). b := 1.0. c := 1.0 + (0.5*Epsilon). self assert: (a = b) & (b = c) ==> (a = c). So I'd rather stick to a keyword selector like fuzzyEqual: Again, this definition corresponds more to an Interval arithmetic model. RealInterval >> fuzzyEqual: b ^(self intersectionWith: b) notEmpty Smalltalk has both exact (Integer/Fraction/ScaledDecimals) and inexact (Float) arithmetic, and the semantic of = will vary from exactEqual: to fuzzyEqual:. RealInterval >> exactEqual: b "always false, if a or b are inexact" ^a isExact and: [b isExact and: [a bounds exactEqual: b bounds]] RealInterval >> isExact "self is exact if Card(self) = 1" ^a bounds min exactEqual: a bounds max Don't confuse with = that could simply mean that they represent the same interval RealInterval >> = b ^a bounds exactEqual: b bounds I did not care much of polymorphism (coercion, double dispatching or whatever), but you get the idea. You can also use probability distributions if it better fits your model, but mathematical background might be a bit short... Nicolas
http://www.jsoftware.com/help/primer/tolerance.htm http://jsoftware.com/help/dictionary/d000.htm
Creators of these languages put a lot of considiration into this and it I think they got it right. It may be too radical to redefine comparison of real values in Smalltalk (although it still makes sense to do so in practical terms) but the discussed test is just a blind shot into a sky. The user should be discouraged to rely on a such comparison.
regards, Â Danil
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Hernan, floating point values are fractions of the form +/- m * 2^k for positive integers m of up to a certain number of bits. Your example requires 13/10 = m * 2^k which is not possible. In slow motion... 2^k = 13/10m To get rid of 13, m must be 13*n... 2^k = 1/10n Now, 1/10 = 1/5 * 1/2, so... 2^{k+1} = 1/5n and then we reach n 2^{k+1} = 1/5 which is absurd for integer n, k. Andres. 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.
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>
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/
2009/7/8 Michael van der Gulik <mikevdg@gmail.com>:
2009/7/8 Hernan Wilkinson <hernan.wilkinson@gmail.com>
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...
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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.
2009/7/8 Igor Stasenko <siguctua@gmail.com>:
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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 < avalloud@smalltalk.comcastbiz.net> 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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
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 <altobarba@gmail.com>:
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 <avalloud@smalltalk.comcastbiz.net> 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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Hope is for sissies (Gregory House, M.D.)
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
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.
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 <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
2009/7/8 John M McIntosh <johnmci@smalltalkconsulting.com>:
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?
Hi John, I missed this one, Yes, numerical compatibility is an issue and I'm fighting to restore it. FYI, Smalltalks are just not compatible at very first step: converting literal decimals to Float... This is because conversion algorithms cumulate several rounding errors... ... all with a different algorithm... ... and because of ANSI laxism about implementation. I corrected Integer>>asFloat, Fraction>>asFloat, Number>>readFrom: and maybe a few others to obtain a uniform behaviour: round to the nearest Float (IEEE 754 default mode round to nearest even). I proposed patches to Squeak/Pharo, gst, Dolphin, ST/X and VW, AFAIK they are integrated in Pharo, gst, Dolphin; partially in Squeak. All is MIT, so other dialects just have to cherry pick. Concerning the exact vs inexact comparison, I raised the subject regularly on various mailing list, but yes it would be great to come to an agreement. Its on the pending bugfix list for Squeak 3.11 at least and Paolo has an opened issue for gst i think. Nicolas
I love these sorts of ridiculous arguments, because the problem is fundamentally a question of design.Do you design accounting for the expectations of reasonable people, or do you design for programmers :) Seriously, there's a bigger question here than should you or should you not compare fractions and reals. The question is "for whom is Pharo written?" IEEE754 run contrary to all of my 18 years of sudying math and using rational numbers. I expect the semantics 1/10 = 10/100 = 100/1000 = 1/2*1/5 = 0.5 * 0.2 based on math in Q. This is no different from expecting 0.1 + 0.2 = 0.3 and not 0.29999999.... If you're building software intended for ordinary people, programmers who rarely do computational mathematics, and for educational use, then defaulting to arbitrary precision scaled math is the right way to go, as it matches the expectations of the audience. If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play. If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem. Consider IEEE754 floats as optimization for a specific class of application, but a de-optimization for all other uses. Now if you're only designing Pharo for people who program IEEE754 float intensive applications, then by all means, go right ahead and make them the default. Dave -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
Dave, I certainly share your opinion about these german discussions. They are ridiculous indeed. But then mathematics are ridiculous too. Who cares about maths in real life? And IT, except among these circles of geeks, common, isn't it a wonderful way to waste our time? In squeak kernel, it happens that floats are used in graphics (and sounds but who cares) Not sure the optimization is premature but yes, we don't need them: we have a rectangular grid of pixels after all, so the most elementary Morphic geometry problem that don't have a solution in Q as you might have learned in your 18 years of studying math, will have an approximate solution in Q, and that's what we are interested in to just draw a Form. Now I challenge you to solve all these little geometry problem in integer arithmetic and remove Float from a Squeak image. If brave enough, you can attempt to use the AlgebraicNumber from MathMorph, just for beauty, then approximate with a Fraction and let BitBlt round to the nearest pixel at the end. I guess you gonna miss pretty soon those imperfect inexact Float of the unreasonnable people. Then you will realize that these pixels are just hardware detail and that you should better work at a higher level where you need those algebraic and other irrational numbers. Unfortunately, even if you manage to create a beautiful computer algebra system with exact representation of these mathematical beings, it will still be a pain to descend to hardware. Of course, if you just want to use your math strength to add decimal numbers, as your examples show, that's were these ScaledDecimal fit perfectly. If you just want to tell every body to use ScaledDecimal where they expect ScaledDecimal, that's a good point, and I join my voice. But if you consider Float are unecessary optimizations except for some engineers like me, I can't agree. You must be using Squeak in console mode ;) Nicolas 2009/7/8 David Goehrig <dave@nexttolast.com>:
I love these sorts of ridiculous arguments, because the problem is fundamentally a question of design. Do you design accounting for the expectations of reasonable people, or do you design for programmers :) Seriously, there's a bigger question here than should you or should you not compare fractions and reals. The question is "for whom is Pharo written?" IEEE754  run contrary to all of my 18 years of sudying math and using rational numbers. I expect the semantics 1/10 = 10/100 = 100/1000 = 1/2*1/5 = 0.5 * 0.2 based on math in Q. This is no different from expecting 0.1 + 0.2 = 0.3 and not 0.29999999.... If you're building software intended for ordinary people, programmers who rarely do computational mathematics, and for educational use, then defaulting to arbitrary precision scaled math is the right way to go, as it matches the expectations of the audience. If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play.  If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem. Consider IEEE754 floats as optimization for a specific class of application, but a de-optimization for all other uses. Now if you're only designing Pharo for people who program IEEE754 float intensive applications, then by all means, go right ahead and make them the default.
Dave -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Wed, Jul 8, 2009 at 5:30 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I guess you gonna miss pretty soon those imperfect inexact Float of the unreasonnable people.
Nicolas please read what I wrote: If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play. If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem. The case of the core drawing engine is a special case. You would optimize this case specially, knowing full well that it is a critical system loop that affects the performance of everything else. But turning around and saying that because this core loop requires optimization, that this optimization technique should be the default is a total non sequitur. One special case does not define what the general case should be. When making a fundamental design decision as to what a sane default is, you need to look at what the non-expert using the system will expect. Saying that "you should know IEEE 754 float math" isn't helpful. Skilled professionals make mistakes with floating point math every day. Telling a child in grammar school that their program doesn't work because they don't understand IEEE 754 math is equally absurd. Design decisions should not be driven by implementation optimization requirements. Doing so only places the incidental preferences of the system implementors over the needs of those who will use it. Dave -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
2009/7/9 David Goehrig <dave@nexttolast.com>:
On Wed, Jul 8, 2009 at 5:30 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I guess you gonna miss pretty soon those imperfect inexact Float of the unreasonnable people.
Nicolas please read what I wrote:
If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play.  If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem.
The case of the core drawing engine is a special case. You would optimize this case specially, knowing full well that it is a critical system loop that affects the performance of everything else.  But turning around and saying that because this core loop requires optimization, that this optimization technique should be the default is a total non sequitur.  One special case does not define what the general case should be.
Your arguments sound reasonable to me. But still the're not giving the answer why (13/10) should be equal to 1.3 I can see the only exit, which may meet your (inexperienced users) expectations: - replace the Float binding in SystemDictionary with ScaledDecimal - and rename current Float class to InexactFloat and deal & live with all consequences of such refactoring..
When making a fundamental design decision as to what a sane default is, you need to look at what the non-expert using the system will expect.  Saying that "you should know IEEE 754 float math" isn't helpful.  Skilled professionals make mistakes with floating point math every day.  Telling a child in grammar school that their program doesn't work because they don't understand IEEE 754 math is equally absurd. Design decisions should not be driven by implementation optimization requirements.  Doing so only places the incidental preferences of the system implementors over the needs of those who will use it.
Dave
-- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
Hi dave thanks for your email because it makes me realizing something important: Computer float numbers are NOT math float numbers. Let us accept it.
I guess you gonna miss pretty soon those imperfect inexact Float of the unreasonnable people.
Nicolas please read what I wrote:
If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play. If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem. The case of the core drawing engine is a special case. You would optimize this case specially, knowing full well that it is a critical system loop that affects the performance of everything else. But turning around and saying that because this core loop requires optimization, that this optimization technique should be the default is a total non sequitur. One special case does not define what the general case should be.
I did not read the fix of nicolas as an optimization, more like a way to fix the wrong behavior of abstraction we offers. I would be in favor to remove = on floats to raise the awareness that it does not make sense.
When making a fundamental design decision as to what a sane default is, you need to look at what the non-expert using the system will expect.
as programmer we should be expert to the point we understand float = is nonsense.
Saying that "you should know IEEE 754 float math" isn't helpful. Skilled professionals make mistakes with floating point math every day.
Exact this is why we should not confort them in this attitude by having a system that make them think that float equality make sense.
Telling a child in grammar school that their program doesn't work because they don't understand IEEE 754 math is equally absurd.
But telling a kid: Floats are not real float numbers so do not use them as such. Once my math teacher asked us to computer a function limit and funnily when you type it on a computer at that time you would got a factor 7 between the math and computer. So we learned that there is a difference between math and computer.
Design decisions should not be driven by implementation optimization requirements. Doing so only places the incidental preferences of the system implementors over the needs of those who will use it.
Exact. What nicolas is doing is not an optimization: this is fixing reality. Your hardware is real and it dictactes all the errors **you** will do, if the language does not offer you the right hardware abstraction. Computer float numbers are NOT math float numbers. Let us accept it.
Dave
-- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/ _______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Stephane,
Computer float numbers are NOT math float numbers. Let us accept it.
I agree with your sentiment. At the risk of being overly precise, I'd state that computer float numbers are not our everyday decimal numbers. I'd avoid the reference to "math" because computer floating point numbers do have significant math behind them. Andres.
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are: 1) Nicolas made a change to avoid confusion when comparing "exact numbers" with "inexact numbers" (among others) 2) This change surprised some people (me in the first place) because it is not how other Smalltalks behave, it is a change in the philosophy of Smalltalk and thus it logically generates disagreements 3) It is clear that Floats are needed due to performance issues, and it is also clear that when performance is not a problem Smalltalk numbers should behave as close as possible (if not equal to) arithmetic. So, I devise these paths: 1) Leave things as they are now in the latest Pharo image, and wait to see if Nicola's change affects real applications (not just tests as it was my case) 2) Same as 1 but making float equals work only when comparing between floats 3) Change the Number hierarchy and make a clear distinction between exact numbers and inexact numbers. Make exact numbers behave as one expects in real math 4) Go back to how things were I think they are pretty much the options... My vote goes for 1 right now. To make 2 we need to experiment more and see how it behaves. I really like 3, I'd love to see that implemented in Smalltalk but doing that model is not easy, it will take time (hey, you have a research track there!), and 4 does not make sense after Nicolas explanations Bye, Hernan. On Thu, Jul 9, 2009 at 6:04 AM, Andres Valloud<avalloud@smalltalk.comcastbiz.net> wrote:
Stephane,
Computer float numbers are NOT math float numbers. Let us accept it.
I agree with your sentiment. Â At the risk of being overly precise, I'd state that computer float numbers are not our everyday decimal numbers. I'd avoid the reference to "math" because computer floating point numbers do have significant math behind them.
Andres.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On 9-Jul-09, at 5:58 AM, Hernan Wilkinson wrote:
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are:
4) Go back to how things were
+1 Frankly I think you could reuse '==' for the *exact* compare between two items in the Number hierarchy and leave '=' as the yes they are *equal* but not the same.... then you could really rummage about and fix/explain/justify why 29347921734912734927349279273499274 == (29347921734912734927349279273499274-1+1) is false and explain why in the same manner as saying (1/10) == 0.1 is false, & resolve why 0.1 == (0.1-0.01+0.01) is false yet 10 == (10-1+1) is true. And yes people do things like use '==' for numbers, for the strangest reasons. -- = = = ======================================================================== John M. McIntosh <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
2009/7/9 John M McIntosh <johnmci@smalltalkconsulting.com>:
On 9-Jul-09, at 5:58 AM, Hernan Wilkinson wrote:
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are:
4) Go back to how things were
+1
Frankly I think you could reuse '==' for the *exact* compare between two items in the Number hierarchy and leave '=' Â as the yes they are *equal* but not the same....
then you could really rummage about and fix/explain/justify why
29347921734912734927349279273499274 == (29347921734912734927349279273499274-1+1) Â is false and explain why in the same manner as saying (1/10) == 0.1 is false, & resolve why 0.1 == (0.1-0.01+0.01) is false yet 10 == (10-1+1) Â is true.
The reason why I would stick to = meaning exactly and some other symbol meaning approximately, is because I expect = to be transitive, while I can very well understand that approximatelyEqual: is not. I would also avoid == because some IdentitySet and the like would start to hate Numbers... unfortunately ~= means different... =~= or using some unicode symbol... (latex \approx)
And yes people do things like use '==' for numbers, for the strangest reasons.
Yes, most because one thought it would be faster (?), but not only... An example is the hackish pattern for enumerating objects that would not work anymore :( like http://bugs.squeak.org/view.php?id=2788
-- = = = ======================================================================== John M. McIntosh <johnmci@smalltalkconsulting.com> Â Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. Â http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Regarding the == instead of =, the only thing I can think of is identity checking of small integers, where in VW you get some improvement by using == instead of =. IIRC, I measured 25% faster in a loop that just did == as opposed to =. But, of course, using that kind of code is asking for trouble. John M McIntosh wrote:
On 9-Jul-09, at 5:58 AM, Hernan Wilkinson wrote:
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are:
4) Go back to how things were
+1
Frankly I think you could reuse '==' for the *exact* compare between two items in the Number hierarchy and leave '=' as the yes they are *equal* but not the same....
then you could really rummage about and fix/explain/justify why
29347921734912734927349279273499274 == (29347921734912734927349279273499274-1+1) is false and explain why in the same manner as saying (1/10) == 0.1 is false, & resolve why 0.1 == (0.1-0.01+0.01) is false yet 10 == (10-1+1) is true.
And yes people do things like use '==' for numbers, for the strangest reasons.
-- = = = ======================================================================== John M. McIntosh <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
I would not change the meaning of ==, that is "the same object". Right now 100 factorial == 100 factorial is false, and should stay the same. On Thu, Jul 9, 2009 at 3:33 PM, John M McIntosh < johnmci@smalltalkconsulting.com> wrote:
On 9-Jul-09, at 5:58 AM, Hernan Wilkinson wrote:
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are:
4) Go back to how things were
+1
Frankly I think you could reuse '==' for the *exact* compare between two items in the Number hierarchy and leave '=' as the yes they are *equal* but not the same....
then you could really rummage about and fix/explain/justify why
29347921734912734927349279273499274 == (29347921734912734927349279273499274-1+1) is false and explain why in the same manner as saying (1/10) == 0.1 is false, & resolve why 0.1 == (0.1-0.01+0.01) is false yet 10 == (10-1+1) is true.
And yes people do things like use '==' for numbers, for the strangest reasons.
-- = = = ======================================================================== John M. McIntosh <johnmci@smalltalkconsulting.com> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Jul 9, 2009, at 2:58 PM, Hernan Wilkinson wrote:
So, Stef, what do we do? :-) I think we have discussed very interesting things is this thread. My conclusions are:
1) Nicolas made a change to avoid confusion when comparing "exact numbers" with "inexact numbers" (among others) 2) This change surprised some people (me in the first place) because it is not how other Smalltalks behave, it is a change in the philosophy of Smalltalk and thus it logically generates disagreements
I do not think that this is a change in philosophy. Clearly you cannot hide the limited nature of float compare to their intellectual/math counterpart.
3) It is clear that Floats are needed due to performance issues, and it is also clear that when performance is not a problem Smalltalk numbers should behave as close as possible (if not equal to) arithmetic.
So, I devise these paths: 1) Leave things as they are now in the latest Pharo image, and wait to see if Nicola's change affects real applications (not just tests as it was my case) 2) Same as 1 but making float equals work only when comparing between floats
Why not. I would like to have a consistent behavior: not true if this is 0.5 and false in 0.3
3) Change the Number hierarchy and make a clear distinction between exact numbers and inexact numbers. Make exact numbers behave as one expects in real math 4) Go back to how things were
yeap
I think they are pretty much the options... My vote goes for 1 right now. To make 2 we need to experiment more and see how it behaves. I really like 3, I'd love to see that implemented in Smalltalk but doing that model is not easy, it will take time (hey, you have a research track there!), and 4 does not make sense after Nicolas explanations
We learned all something today :) So this is a positive experience.
Bye, Hernan.
On Thu, Jul 9, 2009 at 6:04 AM, Andres Valloud<avalloud@smalltalk.comcastbiz.net> wrote:
Stephane,
Computer float numbers are NOT math float numbers. Let us accept it.
I agree with your sentiment. At the risk of being overly precise, I'd state that computer float numbers are not our everyday decimal numbers. I'd avoid the reference to "math" because computer floating point numbers do have significant math behind them.
Andres.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Dave, I plainly agree about 1.3, it doesn't need to be approximated. Our opinion diverge because I pretend you can't go very far with exact computations. I want elementary users to know that the diagonal length of the square has to be approximated for practical means. sqrt(2) is not a rational, this is independent of any implementation. This happens as soon as our users draws a triangle and want to measure perimeter. I think that the notion of error bounds is essential and I prefer to have grown up users. Even without knowing details of Floating point operations, they'll have to know about inexact approximated computations. That certainly won't prevent our skilled "experts" making mistakes everyday with FPU, but education might reduce level of false assumptions, and enlighten sources of encountered problems. Smalltalk is a good tool for such a deeper education. You can stay at the surface, but you can also always peel the onion and discover another level. And if you are more advanced and not satisfied, you can also implement AlgebraicNumber, isn't that just beautiful? My point is to have a good floating point model underneath, as consistent as possible mathematically, reducing unecessary rounding errors introduced at image level, and reflecting state of the art, be it the imperfect IEEE 754. Smalltalk does not have to waste ULPs just because we consider this stuff as dirty wrt to the "pure" integers and decided not to care ;) Exact vs inexact comparison is just a piece of this puzzle. It is nonetheless a good point that the discussion switches to: where should we use Float and where should we use ScaledDecimal. I did not decide to use Float for representing 1.3, it was there at the origin. Even st80 did not have ScaledDecimal. You see, my change is very good after all because half of our highly educated users are surprised to re-discover (13/10) ~= 1.3e0 :) The next step will be to change ScaledDecimal ugly specifications, because no one will be satisfied very long with 0.5s*0.5s -> 0.3s. Nicolas 2009/7/9 David Goehrig <dave@nexttolast.com>:
On Wed, Jul 8, 2009 at 5:30 PM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I guess you gonna miss pretty soon those imperfect inexact Float of the unreasonnable people.
Nicolas please read what I wrote:
If you're defining the default behavior of numbers in the system, the principle of "thou shall not commit premature optimization" should come into play.  If you're that desperately in need of floating point speed, you're also probably capable of applying that and other optimization techniques accordingly, as befits your problem.
The case of the core drawing engine is a special case. You would optimize this case specially, knowing full well that it is a critical system loop that affects the performance of everything else.  But turning around and saying that because this core loop requires optimization, that this optimization technique should be the default is a total non sequitur.  One special case does not define what the general case should be. When making a fundamental design decision as to what a sane default is, you need to look at what the non-expert using the system will expect.  Saying that "you should know IEEE 754 float math" isn't helpful.  Skilled professionals make mistakes with floating point math every day.  Telling a child in grammar school that their program doesn't work because they don't understand IEEE 754 math is equally absurd. Design decisions should not be driven by implementation optimization requirements.  Doing so only places the incidental preferences of the system implementors over the needs of those who will use it.
Dave
-- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
It is nonetheless a good point that the discussion switches to: where should we use Float and where should we use ScaledDecimal. I did not decide to use Float for representing 1.3, it was there at the origin. Even st80 did not have ScaledDecimal. You see, my change is very good after all because half of our highly educated users are surprised to re-discover (13/10) ~= 1.3e0 :)
indeed I'm one and I would like the language interface to help him not forgetting that :)
The next step will be to change ScaledDecimal ugly specifications, because no one will be satisfied very long with 0.5s*0.5s -> 0.3s.
Nicolas
On Thu, Jul 9, 2009 at 3:49 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
I want elementary users to know that the diagonal length of the square has to be approximated for practical means. sqrt(2) is not a rational, this is independent of any implementation.
True, but when you deal with a numbers that are irrational, uncomputable, or the rest you expect them not to be represented cleanly. What throws people for a loop is when you do something like type the following in a python interpreter:
0.2 0.20000000000000001
These sorts of simple rounding errors, do weird things when added with iterative processes. What most elementary school users expect is something more along the lines of floating point math that is BCD encoded. Intel has had BCD math operators in their chips since the 8 bit days. It only takes 1 bytes to represent .2 or .1 in 4bit packed BCD. With the exception of numbers that cannot be represented in decimal, the BCD scheme directly mimics what most non-computer science/ non-computer math people expect :) My point is to have a good floating point model underneath, as
consistent as possible mathematically, reducing unecessary rounding errors introduced at image level, and reflecting state of the art, be it the imperfect IEEE 754
And I'm not arguing that at all. I think IEEE754 support is necessary, there is too much useful data encoded in that format. All I am saying is that it is not necessarily the correct design decision to make it the default representation of numbers. There's a lot to be argued in favor of Ocaml and SML NJ's approach of having entirely separate operators for IEEE754 math. Instead of + you use +. instead of - you use -. etc. SML NJ doesn't even let you test equality on floats. Really the sticky bit is do you go to this extent, or do you decide your representation of numbers require encoding suffixes as well. Even st80 did not have ScaledDecimal.
st80 didn't have IEEE754 floats in it either technically. (IEEE754 wasn't published until 1985).
The next step will be to change ScaledDecimal ugly specifications, because no one will be satisfied very long with 0.5s*0.5s -> 0.3s.
I agree here as well. There's no good reason that should be the case, other than an excessive attention to significant digits :) -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
2009/7/9 David Goehrig <dave@nexttolast.com>:
On Thu, Jul 9, 2009 at 3:49 AM, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I want elementary users to know that the diagonal length of the square has to be approximated for practical means. sqrt(2) is not a rational, this is independent of any implementation.
True, but when you deal with a numbers that are irrational, uncomputable, or the rest you expect them not to be represented cleanly. Â What throws people for a loop is when you do something like type the following in a python interpreter:
0.2 0.20000000000000001 These sorts of simple rounding errors, do weird things when added with iterative processes.
I guess this happens because they want a guaranty the number will be read back the same. Java do it too AFAIK. Smalltalk has an absPrintExactlyOn:base: which is not used (it should be!) but is far better if I remember and avoid these extra decimals (it comes from scheme).
What most elementary school users expect is something more along the lines of floating point math that is BCD encoded. Â Intel has had BCD math operators in their chips since the 8 bit days. Â It only takes 1 bytes to represent .2 or .1 in 4bit packed BCD. Â With the exception of numbers that cannot be represented in decimal, the BCD scheme directly mimics what most non-computer science/ non-computer math people expect :) My point is to have a good floating point model underneath, as
consistent as possible mathematically, reducing unecessary rounding errors introduced at image level, and reflecting state of the art, be it the imperfect IEEE 754
And I'm not arguing that at all. Â I think IEEE754 support is necessary, there is too much useful data encoded in that format. Â All I am saying is that it is not necessarily the correct design decision to make it the default representation of numbers. Â There's a lot to be argued in favor of Ocaml and SML NJ's approach of having entirely separate operators for IEEE754 math. Instead of + you use +. instead of - you use -. etc. Â SML NJ doesn't even let you test equality on floats. Â Really the sticky bit is do you go to this extent, or do you decide your representation of numbers require encoding suffixes as well.
Maybe that's worth a try, but this is independent of my change and the same in every Smalltalk dialect. This part of the discussion is a good spin off of the change. My plan would be to differentiate the literals (1.3e or ~1.3, I don't care), but keep the same selectors +,-,*,/ This would enable algorithms to work with both kind of numbers (at your own risks). Eventually, yes, additional selectors could be added meaning exact addition or inexact addition, and those would cause DNU if you don't provide the right number. For paranoid only :)
 Even st80 did not have ScaledDecimal.
st80 didn't have IEEE754 floats in it either technically. Â (IEEE754 wasn't published until 1985).
The next step will be to change ScaledDecimal ugly specifications, because no one will be satisfied very long with 0.5s*0.5s -> 0.3s.
 I agree here as well.  There's no good reason that should be the case, other than an excessive attention to significant digits :) -- -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
David Goehrig wrote:
IEEE754 run contrary to all of my 18 years of sudying math and using rational numbers.
I find that a bit difficult to accept because numerical analysis courses in colleges and universities describe floating point arithmetic as a basis for the material. Really: without knowing how floating point arithmetic works, then it's going to be considerably harder to do applied math work. Also, I don't see how anybody could mount an argument against floating point arithmetic on math grounds when e.g.: Knuth devotes a significant number of pages of The Art of Computer Programming to them. Not to say that Knuth has to be right, but... Andres.
participants (11)
-
Andres Valloud -
danil osipchuk -
David Goehrig -
Hernan Wilkinson -
Ignacio Vivona -
Igor Stasenko -
John M McIntosh -
Michael van der Gulik -
Nicolas Cellier -
Reinout Heeck -
Stéphane Ducasse