Large Fraction asFloat do overflow and answer Float infinity. ((11 raisedTo: 400) / 2) asFloat = Float infinity. "is true" So far, nothing wrong, except i prefer exception, but that was another discussion.
But then they also equal Float infinity, and that sound strange to me: ((11 raisedTo: 400) / 2) = Float inifinity. "is true"
What is bad in this behavior ? It is that you don't have equality transitivity property any more, and that is a flaw: ((11 raisedTo: 400) / 2) = Float inifinity. "is true" ((13 raisedTo: 400) / 2) = Float inifinity. "is true" ((11 raisedTo: 400) / 2) = ((13 raisedTo: 400) / 2). "is false"
Then you can expect very weird bugs again in Sets. Add these 3 objects to a Set. Since transitivity is broken, the size of the set will vary according to the order you will add objects to it, the hash code algorithm and the set capacity. Something very nasty.
Sure, few people use Large Fractions, and knowing this, they'd rather not, but this is not the right argument.
Also, the hash correction i'am proposing is likely to make things worse. So we have to fix this one. Any idea but testing for infinity in adaptToFraction:andSend: / adaptToFloat:andSend: ?
This is another reason why i really prefer arithmetic exceptions: handle such case. But i cannot move to arithmetic exception alone.
Wow. Great catch. Clearly, this is broken. I think we need to change this coercion to something that deals with the issue properly (e.g., responding false to the comparison in question). Any ideas how to fix that?
Cheers, - Andreas
nicolas cellier wrote:
Large Fraction asFloat do overflow and answer Float infinity. ((11 raisedTo: 400) / 2) asFloat = Float infinity. "is true" So far, nothing wrong, except i prefer exception, but that was another discussion.
But then they also equal Float infinity, and that sound strange to me: ((11 raisedTo: 400) / 2) = Float inifinity. "is true"
What is bad in this behavior ? It is that you don't have equality transitivity property any more, and that is a flaw: ((11 raisedTo: 400) / 2) = Float inifinity. "is true" ((13 raisedTo: 400) / 2) = Float inifinity. "is true" ((11 raisedTo: 400) / 2) = ((13 raisedTo: 400) / 2). "is false"
Then you can expect very weird bugs again in Sets. Add these 3 objects to a Set. Since transitivity is broken, the size of the set will vary according to the order you will add objects to it, the hash code algorithm and the set capacity. Something very nasty.
Sure, few people use Large Fractions, and knowing this, they'd rather not, but this is not the right argument.
Also, the hash correction i'am proposing is likely to make things worse. So we have to fix this one. Any idea but testing for infinity in adaptToFraction:andSend: / adaptToFloat:andSend: ?
This is another reason why i really prefer arithmetic exceptions: handle such case. But i cannot move to arithmetic exception alone.
Hi Andreas,
I agree we should answer false to equality test, unless exact arithmetic. Note that (1/3) asFloat asFraction = (1/3) answer false since asTrueFraction is used, but (1/2) asFloat asFraction = (1/2) is true, and that is exactly how we like it.
I think we should change coercion algorithm for equality test relying on the asTrueFraction, but not touch + * - / since it would break lot of code. This could be something like:
Float>>adaptToFraction: rcvr andSend: selector ^selector = #= ifTrue: [[rcvr = self asTrueFraction] "have to handle NaN and Infinity" on: Error do: [:exc | exc return: false]] ifFalse: [rcvr asFloat perform: selector with: self].
same in Fraction>>adpatToFloat: rcvr andSend: selector
This does also apply to < > <= >= ~= (some are inherited and need not being handled, some must be handled the same way as =, except error handling block because we cannot compare to NaN and should raise an error...). So we have to complexify above method a bit. If it becomes too complex, we'll have to use more specialized selectors.
Note that same stuff is to be done for Float/Integer coercion: | a b c | a := 16rFFFFFFFFFFFFF81. b := 16rFFFFFFFFFFFFF82. c := a asFloat. {a = b. a = c. b = c.}
Maybe we can also expect advices from other Smalltalkers, and make various dialect response more uniform on such a Kernel subject. I went on vwnc mailing list with these, but no answer yet.
Agree ?
Nicolas
Le Mardi 28 Mars 2006 12:45, Andreas Raab a écrit :
Wow. Great catch. Clearly, this is broken. I think we need to change this coercion to something that deals with the issue properly (e.g., responding false to the comparison in question). Any ideas how to fix that?
Cheers,
- Andreas
Nicolas Thanks for all these emails. Keep going :) For the compatibility between dialects we should not dream (else we would not have new calling initialize which is extremely cool as a teacher and programmer too). My feeling is that if we can improve squeak + document the problem with tests + evaluate how we can move without breaking too much existing code then we win :)
Stef
Hi Andreas,
I agree we should answer false to equality test, unless exact arithmetic. Note that (1/3) asFloat asFraction = (1/3) answer false since asTrueFraction is used, but (1/2) asFloat asFraction = (1/2) is true, and that is exactly how we like it.
I think we should change coercion algorithm for equality test relying on the asTrueFraction, but not touch + * - / since it would break lot of code. This could be something like:
Float>>adaptToFraction: rcvr andSend: selector ^selector = #= ifTrue: [[rcvr = self asTrueFraction] "have to handle NaN and Infinity" on: Error do: [:exc | exc return: false]] ifFalse: [rcvr asFloat perform: selector with: self].
same in Fraction>>adpatToFloat: rcvr andSend: selector
This does also apply to < > <= >= ~= (some are inherited and need not being handled, some must be handled the same way as =, except error handling block because we cannot compare to NaN and should raise an error...). So we have to complexify above method a bit. If it becomes too complex, we'll have to use more specialized selectors.
Note that same stuff is to be done for Float/Integer coercion: | a b c | a := 16rFFFFFFFFFFFFF81. b := 16rFFFFFFFFFFFFF82. c := a asFloat. {a = b. a = c. b = c.}
Maybe we can also expect advices from other Smalltalkers, and make various dialect response more uniform on such a Kernel subject. I went on vwnc mailing list with these, but no answer yet.
Agree ?
Nicolas
Le Mardi 28 Mars 2006 12:45, Andreas Raab a écrit :
Wow. Great catch. Clearly, this is broken. I think we need to change this coercion to something that deals with the issue properly (e.g., responding false to the comparison in question). Any ideas how to fix that?
Cheers,
- Andreas
OK I put it on http://bugs.impara.de/view.php?id=3374
and start to implement my response.
Nicolas
Le Mardi 28 Mars 2006 22:39, vous avez écrit :
Nicolas Thanks for all these emails. Keep going :) For the compatibility between dialects we should not dream (else we would not have new calling initialize which is extremely cool as a teacher and programmer too). My feeling is that if we can improve squeak + document the problem with tests + evaluate how we can move without breaking too much existing code then we win :)
Stef
squeak-dev@lists.squeakfoundation.org