[Pharo-project] NaN thoughts (Was: Re: Issue 940: (13/10) = 1.3 returns false)
Btw, Nicolas, in some past, i have proposed to exclude NaN from Float(s) at all by making: NaN is a singleton instance of class NotANumber and change all VM floating point primitives to return such singleton in case if computation result is NaN. NotANumber says for itself: NaN isNumber == false What do you think about it? (Opinion of others is valuable too). 2009/7/8 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
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
_______________________________________________ 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.
Would NaN be polymorphic with floats? Igor Stasenko wrote:
Btw, Nicolas,
in some past, i have proposed to exclude NaN from Float(s) at all by making: NaN is a singleton instance of class NotANumber and change all VM floating point primitives to return such singleton in case if computation result is NaN.
NotANumber says for itself:
NaN isNumber == false
What do you think about it? (Opinion of others is valuable too).
2009/7/8 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
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
_______________________________________________ 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 .
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? It should work... Igor Stasenko wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- Best regards, Igor Stasenko AKA sig.
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? Â It should work...
Sure, it should. What prevents you from implementing it as: NotANumber>>+ number ^ self NotANumber>>adaptToNumber: rcvr andSend: selector selector == #+ ifTrue:[^self]. selector == #* ifTrue:[^self ]. selector == #- ifTrue:[^self ]. selector == #/ ifTrue:[^self]. ^super adaptToNumber: rcvr andSend: selector and so on..
Igor Stasenko wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- 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
-- Best regards, Igor Stasenko AKA sig.
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? Â It should work...
Easy with double dispatching. More boring is to coerce a (Float nan) created by a call to an external library into a (Smalltalk at: #Nan).
Igor Stasenko wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- 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 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? Â It should work...
Easy with double dispatching. More boring is to coerce a (Float nan) created by a call to an external library into a (Smalltalk at: #Nan).
I don't think so. The are few places where you need to change things, like in Interpreter>>floatObjectOf: aFloat to test against Nan, and return a NotANumber singleton instead of creating a new Float instance.
Igor Stasenko wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- 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.
2009/7/8 Igor Stasenko <siguctua@gmail.com>:
2009/7/8 Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com>:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? Â It should work...
Easy with double dispatching. More boring is to coerce a (Float nan) created by a call to an external library into a (Smalltalk at: #Nan).
I don't think so. The are few places where you need to change things, like in  Interpreter>>floatObjectOf: aFloat to test against Nan, and return a NotANumber singleton instead of creating a new Float instance.
As I don't use VMMaker every day, last time it took me 3 hours to produce a VM (retrieving links, downloading, working around Monticello 1.5 initialization problem, and messing with directory structure and configure options). Just to apply an existing change... That's what I call boring :) But in theory, I agree, that should be easy. Nicolas
Igor Stasenko wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- 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
On Jul 8, 2009, at 12:53 PM, Andres Valloud wrote:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? It should work...
It will break further down the line though: (1.0 + NaN) < (1.0 + NaN) should that return NaB (not a Boolean)? Shouldn't obtaining NaN from arithmetic be modeled as a resumable exception, so the calling code can decide what kind of object to return as the value? (Instead of only one choice being hardwired in the system). R -
FWIW... VW has two choices... a) fail the primitives when the answer is INF or NaN, or b) return whatever the FPU says. Also, NaN and INF are regular instances of Float and Double... Reinout Heeck wrote:
On Jul 8, 2009, at 12:53 PM, Andres Valloud wrote:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? It should work...
It will break further down the line though:
(1.0 + NaN) < (1.0 + NaN)
should that return NaB (not a Boolean)?
Shouldn't obtaining NaN from arithmetic be modeled as a resumable exception, so the calling code can decide what kind of object to return as the value? (Instead of only one choice being hardwired in the system).
R -
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
FWIW... VW has two choices... a) fail the primitives when the answer is INF or NaN, or b) return whatever the FPU says. Â Also, NaN and INF are regular instances of Float and Double...
What if some part of the code rely on signalling an Exception , and another part rely on answering exceptional values? Nicolas
Well, that's going to be an issue because the parts of the code will see different VM behavior. Of course, however, the parts of the application can change the VM's behavior on the fly to do as they like. In general, however, I'd expect that kind of stuff to be rather problematic. What would you do? Nicolas Cellier wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
FWIW... VW has two choices... a) fail the primitives when the answer is INF or NaN, or b) return whatever the FPU says. Also, NaN and INF are regular instances of Float and Double...
What if some part of the code rely on signalling an Exception , and another part rely on answering exceptional values?
Nicolas
I don't know :( In external world (C) i guess libraries should care of saving/restoring FPU state. For MultiThread, I guess this saving/restoring of FPU state occurs automatically when switching thread... We could mimic this at process switch with Process-bound variables... To limit the overhead, only Process with a declared interest in FPU could perform a Pre-activate, Pre-suspend action. Maybe something like: FPU >> changeFPUstatus: aFPUstatus (Processor activeProcess) saveSuspendedFPUStatus; setActivatedFPUStatus: aFPUstatus FPU setFPUstatus: aFPUstatus. Process >> saveSuspendedFPUStatus suspendedFPUstatus ifNil: [suspendedFPUstatus := FPU currentFPUstatus ]. Process >> suspend suspendedFPUstatus ifNotNil: [FPU setFPUstatus: suspendedFPUstatus ]. self suspendCore. Process >> activate activatedFPUstatus ifNotNil: [FPU changeFPUstatus: activatedFPUstatus]. self activateCore. Process >> restoreSuspendedFPUStatus suspendedFPUstatus ifNotNil: [ FPU setFPUstatus: suspendedFPUstatus. suspendedFPUstatus := activatedFPUstatus := nil]. Or more ellaborated with a statusStack... Nicolas 2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Well, that's going to be an issue because the parts of the code will see different VM behavior. Â Of course, however, the parts of the application can change the VM's behavior on the fly to do as they like. Â In general, however, I'd expect that kind of stuff to be rather problematic. Â What would you do?
Nicolas Cellier wrote:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
FWIW... VW has two choices... a) fail the primitives when the answer is INF or NaN, or b) return whatever the FPU says. Â Also, NaN and INF are regular instances of Float and Double...
What if some part of the code rely on signalling an Exception , and another part rely on answering exceptional values?
Nicolas
_______________________________________________ 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 1:05 PM, Andres Valloud wrote:
FWIW... VW has two choices... a) fail the primitives when the answer is INF or NaN, or b) return whatever the FPU says. Also, NaN and INF are regular instances of Float and Double...
Moreover: if 1.0/0.0 yields a NaN Float and 1.0d/0.0d yields a NaN Double, what should 1/0 yield? (And would that be a different NaN than (1/2) / 0 yields?) R -
Reinout Heeck wrote:
On Jul 8, 2009, at 12:53 PM, Andres Valloud wrote:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? It should work...
It will break further down the line though:
(1.0 + NaN) < (1.0 + NaN)
should that return NaB (not a Boolean)?
Shouldn't obtaining NaN from arithmetic be modeled as a resumable exception, so the calling code can decide what kind of object to return as the value? (Instead of only one choice being hardwired in the system).
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 Reinout Heeck <reinz@desk.org>:
On Jul 8, 2009, at 12:53 PM, Andres Valloud wrote:
Well, but on the other hand, what happens when you do things like 1.0 + NaN or NaN + 1.0? Â It should work...
It will break further down the line though:
(1.0 + NaN) < (1.0 + NaN)
should that return NaB (not a Boolean)?
Shouldn't obtaining NaN from arithmetic be modeled as a resumable exception, so the calling code can decide what kind of object to return as the value? (Instead of only one choice being hardwired in the system).
IMO, that's the main interest in NaN class: make the Exception behaviour programmable from within the image. Nicolas
R -
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
There was a Parcplace package extending VW with such classes (NaN, Infinity, Infinitesimal), and I liked it (can't remember if inheriting from Magnitude though). The main difference I see with state of the art FPU practice is Exception handling: that does force Exception handling where users might prefer traditional exceptional values... Nicolas 2009/7/8 Igor Stasenko <siguctua@gmail.com>:
2009/7/8 Andres Valloud <avalloud@smalltalk.comcastbiz.net>:
Would NaN be polymorphic with floats?
Do you mean , be a part of Number/Float class hierarchy? Answer is: no. Because NotANumber is not a number :)
-- 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
participants (4)
-
Andres Valloud -
Igor Stasenko -
Nicolas Cellier -
Reinout Heeck