754 decide NaN != NaN despite being illogical?

This is a follow up question to What is the rationale for all comparisons returning false for IEEE754 NaN values? (I think this is better as another question than a comment). It has a very good answer which is missing exactly 1 important thing: why is NaN != NaN ?

I understand that NaN is unordered compared to numbers and thus NaN < x and NaN > x are both always false. But that doesn't explain why equality is backwards. To quote the answer of the question I linked to:

it was necessary to provide programmers with a convenient and efficient means of detecting NaN values that didn't depend on programming languages providing something like isNan()

Ok then:

if((0/0) == x) print "I found NaN!";
//using 0/0 is more readable than using 0x7fc00000 or 0x7ff8000000000000

That's convenient, efficient, and doesn't rely on a programming language provided construct. Even if the programming language doesn't have a global NaN defined you can easily make a local (or global) variable yourself.

A single extra operation is certainly not inefficient, especially since the FPU has a hard-coded response (no calculation needed). Using 0/0 is also more programmer convenient than the illogical x!=x .

A program rarely needs to check for NaN and having a single extra operation per check is not going to be the reason a program is inefficient. Likewise there's no program so restrained that it can't handle a single extra variable, especially a temporary one.

To me the argument "I need NaN!=NaN so that I can detect it" doesn't make sense: it's exactly the same argument as "I need Infinity!=Infinity so that I can detect it". No you don't, just compare it to 1/0 like everyone else.

So my question is much more narrow than the original question: Why is NaN != NaN ?

I can't tell if this has been asked before since there's plenty of duplicates of the original question.

Side note:

NaN == NaN isn't going to change now

while the FPU won't change now, some programming languages have already changed so that NaN == NaN is true.

Edit:

Let me try to clarify why I haven't accepted any answer so far. I have read the comments so far and I'm sorry I've dropped the ball: instead of explaining why I disagree I just asked "why" hoping you'd give a different reason. So let me try to explain my perspective better.

Infinity and NaN are similar in many ways.

  • Both Infinity and NaN are concepts. Infinity isn't a number it is a concept of never ending. If x is Infinity then it represents that x is endless. NaN isn't a number (duh) and represents an invalid state or something not mathematically valid. For mathematic completeness: infinity is debatably a "number" however floating point numbers approximate real numbers (although they are closer to rational numbers) and infinity is definitively not in the real numbers. Therefore as far as the FPU and real number line are concerned infinity (all types) is not a number (as per the domain's definition of "number").
  • Equality is not always a numeric equality. General equality is only numeric equality if both operands are numbers (not concepts) even if the FPU is asked to perform the comparison. General equality is used when one operand is Infinity or NaN in order to see if the other represents the same concept. For example x == Infinity doesn't use numeric equality (since Infinity isn't a number) instead it checks if x represents the concept of positive infinity. I would likewise expect exactly the same thing from x == NaN to return true if x is the concept of "not a number" but this isn't the case (as to why is the point of this question).
  • Both can be retrieved by dividing by 0: 0/0 returns NaN and 1/0 returns Infinity. If your language doesn't have a constant for Infinity then x == (1/0) is the way to compare x to Infinity.
  • Multiple flavors. There are infinitely many types of Infinity (because of cardinality). However the FPU doesn't make any distinctions: Infinity is a general purpose one and the only one available. With these constructs it isn't possible to ask if x is countable infinity for example. NaN has only 1 type conceptually ("not a number") however it has 2 ways it is handled: quiet and signaling. I know nothing about signaling but from my understanding if you tried to compare the equality of a signaling NaN it would throw, therefore since it doesn't have equality it isn't entirely on topic.
  • Bit representation. NaN has many different bit representations but Infinity has only 1 (and 1 for -Infinity). However all representations of NaN are exactly the same value logically because they all represent the same concept of "not a number". There is no distinction to be made between 0x7FF8000000000000 and 0x7FF8000000000001: they mean exactly the same thing and the exact same math is allowed to return either result. You can't ask if x is the sqrt(-1) or if x is log(-1) because both of those will return exactly the same thing: NaN. Similar to how there is only 1 kind of Infinity, there is only 1 type of (quiet) NaN. Yes there are multiple bit representations but one is not greater than the others: the FPU uses special logic to treat them all exactly the same. This is likewise true for -0 which has a different bit than +0 but is treated exactly the same. Therefore the bits are an implementation detail unrelated to logical equality.
  • (Off topic but they also both have special math: x-1 doesn't change the value of Infinity or NaN).
  • So yes I did hear you when you said "equality doesn't make sense because it isn't a number" but I disagree with that statement because if it was true then as per #1 it also wouldn't make sense to compare Infinity (which also isn't a number). Although as per #2 it does make sense to compare non-numbers.

    I have in fact read every answer to the original question (and to Why are floating point infinities, unlike NaNs, equal? which has some related answers). All of the arguments for why NaN != NaN is true boil down to either "because it isn't a number" (already addressed) or "because there are many different bit representations" which is countered by #5.

    I can't think of any logical basis for why NaN should have different equality. I'm not saying that I have accounted for everything: so what have I missed? Is one of my arguments wrong or is there some other reason I hadn't thought of? That's why I've been camping on the word "why". If you disagree then refute me or defend your point. I'm guessing there will be at least 1 counter-point to my above logic and I'm looking forward to hearing it.

    Again I apologize for not including these in the original question since I have been thinking them all along. I'm also sorry that this may cause a big change to the existing answer.


    There are several ways to produce NaN .

    Imagine this:

    double expr1 = 0.0 / 0.0;
    double expr2 = Math.log(-1.0);
    if (expr1 == expr2) {
      // They are the same
    }
    

    These two NaN s, if they had been representable as numbers, would have a high probability of being different values.

    If NaN == NaN would hold, this snippet would have the unexpected result of comparing them as equal. Since most programs do the comparison in terms of what they expect (so they use == , <= , but not !== , !<= ), returning false doesn't make these programs conclude wrong things.

    链接地址: http://www.djcxy.com/p/58504.html

    上一篇: IEEE754中inf == inf的基本原理是什么?

    下一篇: 尽管不合逻辑,754决定NaN!= NaN?