
Since we are now venturing in the realm of python-ideas, I am switching the mailing lists. Please see more below. On Wed, Mar 24, 2010 at 7:31 PM, Mark Dickinson <dickinsm@gmail.com> wrote:
I maybe show my ignorance, but I don't see the significance of bringing Decimal nans to the discussion. My answers below apply equally to binary and decimal floating point numbers.
should any Decimal nan compare equal to any other?
Yes.
What if the two nans have different payloads or signs?
They are still equal. Just as 0.0 and -0.0 are now.
I don't think signaling nans can be produced using Python float type. I may be mistaken about this and the answer may be different in some decimal contexts. Nevertheless, I always thought that any operation with an sNaN should raise an exception, so comparing an sNaN with anything, NaN or not, should just raise an exception.
How do decimal nans compare with float nans?
Good question. Does IEEE 754 or rather 854 specify cross-radix comparisons? My answer would be that they should compare equal.
Should Decimal.compare(Decimal('nan'), Decimal('nan')) return 0 rather than nan?
I would think with deprecation of __cmp__, Decimal.compare would not be that useful. I would rather not expand this discussion to what NaN < NaN should return. In my view it should just raise an exception because there is no practical way to propagate NaN through boolean results. Decimal.compare may similarly raise an exception when comparing NaNs. Returning Decimal('nan') seems least useful. With the current NaN properties, I would rather see Decimal.compare return 2 for unordered values.
If not, how do you justify the difference between == and compare?
Just as (a > b or b < a) is currently not equivalent to a != b in the presence of unordered values (i.e. when a and b are of different type).
If so, how do you justify the deviation from the standard on which the decimal modulo is based?
I assume you mean "decimal module" because I don't know what "decimal modulo" is based on. Is that IEEE 854? I need to get a copy of that before I can answer. :-)
As Grace Hopper is reported to have said, "The wonderful thing about standards is that there are so many of them to choose from." As much as I don't like most of the choices that Java designers made, I think they got this one right.
I don't think I can answer this better than Bertrand Meyer: """ Before commenting further let me note the obvious: I am by no means a numerics expert; I know that IEEE 754 was a tremendous advance, and that it was designed by some of the best minds in the field, headed by Velvel Kahan who received a Turing Award in part for that success. So it is quite possible that I am about to bury myself in piles of ridicule. On the other hand I have also learned that (1) ridicule does not kill, so I am game; and more importantly (2) experts are often right but not always, and it is always proper to question their reasoning. So without fear let me not stop at the arguments that “the committee must have voted on this point and they obviously knew what they were doing” and “it is the standard and implemented on zillions of machines, you cannot change it now”. Both are true enough, but not an excuse to censor questions. """ http://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civiliz...
Bertrand Meyer again: """ A few of us who had to examine the issue recently think that — whatever the standard says at the machine level — a programming language should support the venerable properties that equality is reflexive and that assignment yields equality. """ IEEE standards were developed in a different problem domain: hardware or low level programming language design. They may not be appropriate for an object oriented language like Python. Java and recently Eiffel designers seem to have realized that.

On Thu, 25 Mar 2010 02:50:41 -0400 Alexander Belopolsky <alexander.belopolsky@gmail.com> wrote:
Hum, should the above be interpreted as: a = NAN ==> not only a is NAN but also a == NAN and further: b = a ==> b == a ? (Else there should be a distinction between equality assignment and identity assignemt? b = a # ==> a is b and a == b b := a # ==> a is b and possibly a == b ;-) Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

spir ☣ wrote:
Eiffel's position on this seems to be that there should be no distinction -- a copy of a value should always compare equal to the original value, regardless of type. Eiffel even seems to extend this to conversions, so that if you convert an int to a float, the resulting float should compare equal to the original int, even if some precision was lost in the conversion. (Incidentally, that's one principle we would be choosing *not* to follow if we decide to compare floats and Decimals based on their exact values.) -- Greg

On Fri, 26 Mar 2010 14:25:06 +1300 Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Exactly, as I understand Eiffel. And, actually, I tend to support this point of view.
Yes, there is a post-condition equivalent to "assert(newval==val)". That's why (from this point of view):
What do you mean, exactly? There may be a reference type, then the condition is Ref(val)==Ref(newval). Or both type are referent (eg between int and float there may be loss of info in both directions). Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

2010/3/26 Greg Ewing <greg.ewing@canterbury.ac.nz>:
Such equality is not transitive (unless 1000000000 and 1000000001 are equal as ints which would be nonsense). The original problem with NaN is a consequence of an unfortunate decision to unify numeric equality with object equivalence. If they were distinguished, their behavior would be obvious: NaN != NaN NaN eq NaN 0.0 == -0.0 0.0 ne -0.0 42 == 42.0 42 ne 42.0 Hash tables would use object equivalence of course. If you have a type for a time which includes the local time and the time zone, and < > <= >= compare which time is earlier, then numeric == should be true for times denoting the same time through different time zones, but they should not be equivalent. Lisp and Scheme distinguish these relations. -- Marcin Kowalczyk

On Sat, Mar 27, 2010 at 10:21 AM, Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> wrote:
Agreed, except that it's not clear to me that this was actually an unfortunate decision. The results in this context are unfortunate, yes, but it could well be that distinguishing numeric equality and object equivalence would add unacceptable complexity to the language for those trying to learn it. Questions about 'is' versus '==' are especially common on the mailing lists, and adding a third equivalence relation wouldn't help newcomers. Mark

Marcin 'Qrczak' Kowalczyk writes:
What do you mean by that? NaN is a class, not an instance!
As for the other examples, I can only sigh, 'Ah, the joys of "general abstract nonsense".'[1] I have some (abstract) sympathy for Mark's proposal for a with_nonstop_arithmetic context manager, but isn't it really a YAGNI for the Python language? (As opposed to high performance modules like numpy.) Footnotes: [1] I refer to Bourbaki's(?) name for category theory.

I'm missing something from this discussion. Is this an academic exercise or are there scenarios that don't work well with things as they are? It's hard to determine if a suggested change solve the problem without knowing what the problem is. Here's a problem: I find it annoying that in some (other) languages there's no easy way to trap integer overflow. It's easy to write code that's wrong accidentally. But changing the language definition to fail when an overflow happens would break some valid programs. In python, results that return nan or inf aren't exactly silent failures but they are quiet. (Personally, I would have made them non-hashable so you couldn't accidentally stick one in a dict but that's another problem.) Anyway, of silent/quiet failure is the issue, then what we need is a way to make the failure not silent, e.g., wrap it in a try/except block like this that says, convert any nans to NanErrors: try with NanError: blah except NanError: blah Inside this scope, it might be useful to run code that does allow nans, which means we'd also need something like: without NanError: blah This all seems a bit too magic in how it would work. This is along the line of Mark Dickinson's suggestion, but the default behavior should stay the same as it is now. --- Bruce

Bruce Leban writes:
(Personally, I would have made them non-hashable so you couldn't accidentally stick one in a dict but that's another problem.)
No, it's not. AIUI, that is one of the main issues that's being discussed in this thread. Most people seem reasonably satisfied with other behavior, so the discussion bounces back and forth between whether NaNs should be hashable (and, perhaps more often, whether they should all be equal or not), and how any change in identity or equality behavior might affect computations in existing programs.

On 25 Mar 2010, at 07:50 , Alexander Belopolsky wrote:
Excuse me but NaNs propagate right? So we'd have not only float('nan') == float('nan'), but also float('nan') = float('nan') + 1 right? Indeed, any operation on a NaN would return a result equal (and identical?) to itself. I'm not sure that makes more sense than the current behavior (which is at least standard and specified).
IEEE standards were developed in a different problem domain: hardware or low level programming language design.
I don't really agree. They were developed in a problem domain of mapping abstract mathematical concepts to computing. And it's not like they're static and never updated (indeed, IEEE-754 was updated in 2008, if anyone has an IEEE login it would be possible to check the purposes and assumptions the standard set for itself). I believe changing the behavior of nan to have "nan == nan" would be broken, nan is not a "normal" value (or set of values) of the space. Having the option of getting an exception upon getting a nan on the other hand (as the default behavior even, with a switch to the current behavior using contexts similar to decimal's), why not.
http://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civiliz...
It's interesting that Bertrand starts from
I am talking about a value, as in mathematics, not an expression, as in programming
but doesn't seem to consider that, in the first place, the very concept of NaN is due to the limitations of physical space compared to the abstract mathematical concepts involved. The very idea of IEEE-754 floats are a a definite departure from the fundamental laws of mathematics, making Bertrand's final request
It is rather dangerous indeed to depart from the fundamental laws of mathematics.
very weird. Unless you remove floats from your language, you're not dealing with grounds mathematics cover in the first place, you're dealing with a concretization of mathematical ideas, and as all changes in abstraction levels, it will leak one way or another. I'd support "fixing" nan behaviors, but not by making operations on nan reflexive (and nan a normal value, which it isn't) and instead by treating all of them as errors, the same way calling an arbitrary attribute no None results in an AttributeError in Python.

Masklinn wrote:
The fact that one of the operands was a NaN propagates, but it doesn't have to be that particular NaN object. So NaN + 1 could create a new NaN object to return as its result.
They're a departure from the laws of *real numbers*, but Meyer is using the word "mathematics" in a much broader sense here -- meaning any formal system that you can reason about rigorously. If your formal system has a notion of equality but includes values that don't compare equal to themselves, it seriously screws up your ability to reason about it. For Meyer, this is a *big* problem, because making it possible to reason rigorously about programs is something that Eiffel gets really anal about^H^H^H^H^H^H^H^H^H^H ^H^H^H^H^H^H one of the underpinnings of Eiffel's design. The more I think about it, the more I think that the only reason for needing NaNs in the first place is if you don't have, or don't want to use, an exception mechanism. As Meyer points out, treating NaN == NaN as false is not fundamentally any more correct than treating it as true. One interpretation or the other might be appropriate in a particular algorithm, but this needs to be considered on a case-by-case basis. So the *pythonic* way to handle NaNs is not to have them at all, but to raise an exception whenever an operation would produce a NaN. Code that knows what to do can catch the exception and proceed appropriately. Another possibility is to extend the boolean type with a NaB that propagates in the same way as a NaN. But something still has to give somewhere, because what happens when you do this? x = float('nan') y = float('nan') if x == y: ... else: ... If NaN == NaN is a NaB, then neither branch of the 'if' is appopriate, so the only correct thing to do would be to raise an exception when trying to branch on a NaB. So we have three correctness-preserving possibilites: 1) Always raise an exception as soon as a NaN is produced. 2) Propagate NaNs through arithmetic but raise an exception when attempting to compare them. 3) Return a NaB when comparing NaNs, and raise an exception when attempting to branch on a NaB. -- Greg

On Thu, Mar 25, 2010 at 20:01, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
This forces you to explicitly compare them when desired, but it's even simpler than I realized (and doesn't require new functions). def func(a, b): if not isnan(a) and not isnan(b) and a == b: return 1.0 return math.sin(a*b)**(a-b) All it requires is you check for NaN before your normal comparison. It's even backwards compatible with Python 2.6! If that example is a little verbose for you, just make isnan take multiple arguments and return true if any are NaN.
3) Return a NaB when comparing NaNs, and raise an exception when attempting to branch on a NaB.
-- Adam Olsen, aka Rhamphoryncus

On Fri, 26 Mar 2010 15:01:46 +1300 Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
[In a language or a given case where yielding a NaN does not raise an exception from scratch.] It seems to me there are various comparison cases (esp. in an OO language, case 2): -1- Comparing (any) Nan to non_NaN should return False. a = <expr yielding a NaN> b = 1 a == b # ==> False -2- Comparing a given NaN with itself should return True. a = <expr yielding a NaN> b = a a == b # ==> True -3- Comparing various NaNs is the undefined case. Actually, I think it's the only case where a theoretical NaB makes sense. In my opinion, as Greg says, the python way would here be raising an exception. But only in that case. Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

Interestingly, Java departs from IEEE 754 on that last point as well: """ Note that in most cases, for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if d1.doubleValue() == d2.doubleValue() also has the value true. However, there are two exceptions: If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false. If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true. This allows hashtables to operate properly. """ http://java.sun.com/j2se/1.3/docs/api/java/lang/Double.html

IMO, we should go for the simplest of all usage: a NaN singleton, shared by float and Decimal, compares equal to itself, unsortable, no payload. Usage of the payload is hypothetical. Situations where comparing false is "more correct" than comparing true are hypothetical, and grossly outweighed by the situations where comparing true is blatantly correct. IEEE 754 doesn't say NaN should compare false; it says it should compare "unordered". We can't do that as we're not using a 4-way comparison (which wouldn't generalize to complex anyway), so we have to make up our own solution. It might as well fit our needs, rather than nobodies. -- Adam Olsen, aka Rhamphoryncus

On Thu, Mar 25, 2010 at 6:33 PM, Adam Olsen <rhamph@gmail.com> wrote:
I don't think disposing of payloads is much of an option for Decimal: it would break hundreds (literally!) of the decimal testcases, and would mean that the decimal module would no longer comply with the standard it's supposed to be based on. Note that in contrast we're free to alter the meaning of ==, <=, comparisons for the decimal module, since those aren't covered by the standard anyway; someone looking for standards compliance can limit themselves to using Decimal.compare. I much prefer Nick's proposal (in the python-dev bit of this thread: this thread seems to keep moving between python-ideas and python-dev :).
IEEE 754 doesn't say NaN should compare false; it says it should compare "unordered".
Indeed it does.
Not necessarily: the standard already gives solutions to the problem of mapping a 4-way comparison to {true, false}. It defines (in section 5.11) a number of predicates that map the four possible relations (LT, GT, EQ, UN) to true and false. Amongst those predicates are 'compareQuietEqual', which maps EQ to True and LT, GT, UN to False (and hence gives nan == nan --> False), and 'compareSignalingEqual', which does the same but also raises a floating-point exception for UN. It doesn't say anything about how those predicates should be spelled in any particular language, though; currently, Python's == corresponds to compareQuietEqual. Unfortunately neither of those predicates gets us round the reflexivity problem. Mark

On Thu, 25 Mar 2010 02:50:41 -0400 Alexander Belopolsky <alexander.belopolsky@gmail.com> wrote:
Hum, should the above be interpreted as: a = NAN ==> not only a is NAN but also a == NAN and further: b = a ==> b == a ? (Else there should be a distinction between equality assignment and identity assignemt? b = a # ==> a is b and a == b b := a # ==> a is b and possibly a == b ;-) Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

spir ☣ wrote:
Eiffel's position on this seems to be that there should be no distinction -- a copy of a value should always compare equal to the original value, regardless of type. Eiffel even seems to extend this to conversions, so that if you convert an int to a float, the resulting float should compare equal to the original int, even if some precision was lost in the conversion. (Incidentally, that's one principle we would be choosing *not* to follow if we decide to compare floats and Decimals based on their exact values.) -- Greg

On Fri, 26 Mar 2010 14:25:06 +1300 Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Exactly, as I understand Eiffel. And, actually, I tend to support this point of view.
Yes, there is a post-condition equivalent to "assert(newval==val)". That's why (from this point of view):
What do you mean, exactly? There may be a reference type, then the condition is Ref(val)==Ref(newval). Or both type are referent (eg between int and float there may be loss of info in both directions). Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

2010/3/26 Greg Ewing <greg.ewing@canterbury.ac.nz>:
Such equality is not transitive (unless 1000000000 and 1000000001 are equal as ints which would be nonsense). The original problem with NaN is a consequence of an unfortunate decision to unify numeric equality with object equivalence. If they were distinguished, their behavior would be obvious: NaN != NaN NaN eq NaN 0.0 == -0.0 0.0 ne -0.0 42 == 42.0 42 ne 42.0 Hash tables would use object equivalence of course. If you have a type for a time which includes the local time and the time zone, and < > <= >= compare which time is earlier, then numeric == should be true for times denoting the same time through different time zones, but they should not be equivalent. Lisp and Scheme distinguish these relations. -- Marcin Kowalczyk

On Sat, Mar 27, 2010 at 10:21 AM, Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> wrote:
Agreed, except that it's not clear to me that this was actually an unfortunate decision. The results in this context are unfortunate, yes, but it could well be that distinguishing numeric equality and object equivalence would add unacceptable complexity to the language for those trying to learn it. Questions about 'is' versus '==' are especially common on the mailing lists, and adding a third equivalence relation wouldn't help newcomers. Mark

Marcin 'Qrczak' Kowalczyk writes:
What do you mean by that? NaN is a class, not an instance!
As for the other examples, I can only sigh, 'Ah, the joys of "general abstract nonsense".'[1] I have some (abstract) sympathy for Mark's proposal for a with_nonstop_arithmetic context manager, but isn't it really a YAGNI for the Python language? (As opposed to high performance modules like numpy.) Footnotes: [1] I refer to Bourbaki's(?) name for category theory.

I'm missing something from this discussion. Is this an academic exercise or are there scenarios that don't work well with things as they are? It's hard to determine if a suggested change solve the problem without knowing what the problem is. Here's a problem: I find it annoying that in some (other) languages there's no easy way to trap integer overflow. It's easy to write code that's wrong accidentally. But changing the language definition to fail when an overflow happens would break some valid programs. In python, results that return nan or inf aren't exactly silent failures but they are quiet. (Personally, I would have made them non-hashable so you couldn't accidentally stick one in a dict but that's another problem.) Anyway, of silent/quiet failure is the issue, then what we need is a way to make the failure not silent, e.g., wrap it in a try/except block like this that says, convert any nans to NanErrors: try with NanError: blah except NanError: blah Inside this scope, it might be useful to run code that does allow nans, which means we'd also need something like: without NanError: blah This all seems a bit too magic in how it would work. This is along the line of Mark Dickinson's suggestion, but the default behavior should stay the same as it is now. --- Bruce

Bruce Leban writes:
(Personally, I would have made them non-hashable so you couldn't accidentally stick one in a dict but that's another problem.)
No, it's not. AIUI, that is one of the main issues that's being discussed in this thread. Most people seem reasonably satisfied with other behavior, so the discussion bounces back and forth between whether NaNs should be hashable (and, perhaps more often, whether they should all be equal or not), and how any change in identity or equality behavior might affect computations in existing programs.

On 25 Mar 2010, at 07:50 , Alexander Belopolsky wrote:
Excuse me but NaNs propagate right? So we'd have not only float('nan') == float('nan'), but also float('nan') = float('nan') + 1 right? Indeed, any operation on a NaN would return a result equal (and identical?) to itself. I'm not sure that makes more sense than the current behavior (which is at least standard and specified).
IEEE standards were developed in a different problem domain: hardware or low level programming language design.
I don't really agree. They were developed in a problem domain of mapping abstract mathematical concepts to computing. And it's not like they're static and never updated (indeed, IEEE-754 was updated in 2008, if anyone has an IEEE login it would be possible to check the purposes and assumptions the standard set for itself). I believe changing the behavior of nan to have "nan == nan" would be broken, nan is not a "normal" value (or set of values) of the space. Having the option of getting an exception upon getting a nan on the other hand (as the default behavior even, with a switch to the current behavior using contexts similar to decimal's), why not.
http://bertrandmeyer.com/2010/02/06/reflexivity-and-other-pillars-of-civiliz...
It's interesting that Bertrand starts from
I am talking about a value, as in mathematics, not an expression, as in programming
but doesn't seem to consider that, in the first place, the very concept of NaN is due to the limitations of physical space compared to the abstract mathematical concepts involved. The very idea of IEEE-754 floats are a a definite departure from the fundamental laws of mathematics, making Bertrand's final request
It is rather dangerous indeed to depart from the fundamental laws of mathematics.
very weird. Unless you remove floats from your language, you're not dealing with grounds mathematics cover in the first place, you're dealing with a concretization of mathematical ideas, and as all changes in abstraction levels, it will leak one way or another. I'd support "fixing" nan behaviors, but not by making operations on nan reflexive (and nan a normal value, which it isn't) and instead by treating all of them as errors, the same way calling an arbitrary attribute no None results in an AttributeError in Python.

Masklinn wrote:
The fact that one of the operands was a NaN propagates, but it doesn't have to be that particular NaN object. So NaN + 1 could create a new NaN object to return as its result.
They're a departure from the laws of *real numbers*, but Meyer is using the word "mathematics" in a much broader sense here -- meaning any formal system that you can reason about rigorously. If your formal system has a notion of equality but includes values that don't compare equal to themselves, it seriously screws up your ability to reason about it. For Meyer, this is a *big* problem, because making it possible to reason rigorously about programs is something that Eiffel gets really anal about^H^H^H^H^H^H^H^H^H^H ^H^H^H^H^H^H one of the underpinnings of Eiffel's design. The more I think about it, the more I think that the only reason for needing NaNs in the first place is if you don't have, or don't want to use, an exception mechanism. As Meyer points out, treating NaN == NaN as false is not fundamentally any more correct than treating it as true. One interpretation or the other might be appropriate in a particular algorithm, but this needs to be considered on a case-by-case basis. So the *pythonic* way to handle NaNs is not to have them at all, but to raise an exception whenever an operation would produce a NaN. Code that knows what to do can catch the exception and proceed appropriately. Another possibility is to extend the boolean type with a NaB that propagates in the same way as a NaN. But something still has to give somewhere, because what happens when you do this? x = float('nan') y = float('nan') if x == y: ... else: ... If NaN == NaN is a NaB, then neither branch of the 'if' is appopriate, so the only correct thing to do would be to raise an exception when trying to branch on a NaB. So we have three correctness-preserving possibilites: 1) Always raise an exception as soon as a NaN is produced. 2) Propagate NaNs through arithmetic but raise an exception when attempting to compare them. 3) Return a NaB when comparing NaNs, and raise an exception when attempting to branch on a NaB. -- Greg

On Thu, Mar 25, 2010 at 20:01, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
This forces you to explicitly compare them when desired, but it's even simpler than I realized (and doesn't require new functions). def func(a, b): if not isnan(a) and not isnan(b) and a == b: return 1.0 return math.sin(a*b)**(a-b) All it requires is you check for NaN before your normal comparison. It's even backwards compatible with Python 2.6! If that example is a little verbose for you, just make isnan take multiple arguments and return true if any are NaN.
3) Return a NaB when comparing NaNs, and raise an exception when attempting to branch on a NaB.
-- Adam Olsen, aka Rhamphoryncus

On Fri, 26 Mar 2010 15:01:46 +1300 Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
[In a language or a given case where yielding a NaN does not raise an exception from scratch.] It seems to me there are various comparison cases (esp. in an OO language, case 2): -1- Comparing (any) Nan to non_NaN should return False. a = <expr yielding a NaN> b = 1 a == b # ==> False -2- Comparing a given NaN with itself should return True. a = <expr yielding a NaN> b = a a == b # ==> True -3- Comparing various NaNs is the undefined case. Actually, I think it's the only case where a theoretical NaB makes sense. In my opinion, as Greg says, the python way would here be raising an exception. But only in that case. Denis ________________________________ vit esse estrany ☣ spir.wikidot.com

Interestingly, Java departs from IEEE 754 on that last point as well: """ Note that in most cases, for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if d1.doubleValue() == d2.doubleValue() also has the value true. However, there are two exceptions: If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false. If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true. This allows hashtables to operate properly. """ http://java.sun.com/j2se/1.3/docs/api/java/lang/Double.html

IMO, we should go for the simplest of all usage: a NaN singleton, shared by float and Decimal, compares equal to itself, unsortable, no payload. Usage of the payload is hypothetical. Situations where comparing false is "more correct" than comparing true are hypothetical, and grossly outweighed by the situations where comparing true is blatantly correct. IEEE 754 doesn't say NaN should compare false; it says it should compare "unordered". We can't do that as we're not using a 4-way comparison (which wouldn't generalize to complex anyway), so we have to make up our own solution. It might as well fit our needs, rather than nobodies. -- Adam Olsen, aka Rhamphoryncus

On Thu, Mar 25, 2010 at 6:33 PM, Adam Olsen <rhamph@gmail.com> wrote:
I don't think disposing of payloads is much of an option for Decimal: it would break hundreds (literally!) of the decimal testcases, and would mean that the decimal module would no longer comply with the standard it's supposed to be based on. Note that in contrast we're free to alter the meaning of ==, <=, comparisons for the decimal module, since those aren't covered by the standard anyway; someone looking for standards compliance can limit themselves to using Decimal.compare. I much prefer Nick's proposal (in the python-dev bit of this thread: this thread seems to keep moving between python-ideas and python-dev :).
IEEE 754 doesn't say NaN should compare false; it says it should compare "unordered".
Indeed it does.
Not necessarily: the standard already gives solutions to the problem of mapping a 4-way comparison to {true, false}. It defines (in section 5.11) a number of predicates that map the four possible relations (LT, GT, EQ, UN) to true and false. Amongst those predicates are 'compareQuietEqual', which maps EQ to True and LT, GT, UN to False (and hence gives nan == nan --> False), and 'compareSignalingEqual', which does the same but also raises a floating-point exception for UN. It doesn't say anything about how those predicates should be spelled in any particular language, though; currently, Python's == corresponds to compareQuietEqual. Unfortunately neither of those predicates gets us round the reflexivity problem. Mark
participants (9)
-
Adam Olsen
-
Alexander Belopolsky
-
Bruce Leban
-
Greg Ewing
-
Marcin 'Qrczak' Kowalczyk
-
Mark Dickinson
-
Masklinn
-
spir ☣
-
Stephen J. Turnbull