Why Is Double.Nan Not Equal to Itself

Why is double.NaN not equal to itself?

If you are curious, this is what Double.IsNaN looks like:

public static bool IsNaN(double d)
{
return (d != d);
}

Funky, huh?

Why does Double.NaN==Double.NaN return false?

NaN means "Not a Number".

Java Language Specification (JLS) Third Edition says:

An operation that overflows produces a signed infinity, an operation that underflows produces a denormalized value or a signed zero, and an operation that has no mathematically definite result produces NaN. All numeric operations with NaN as an operand produce NaN as a result. As has already been described, NaN is unordered, so a numeric comparison operation involving one or two NaNs returns false and any != comparison involving NaN returns true, including x!=x when x is NaN.

Comparing Double.NaN with itself

The reason for the difference is simple, if not obvious.

If you use the equality operator ==, then you're using the IEEE test for equality.

If you're using the Equals(object) method, then you have to maintain the contract of object.Equals(object). When you implement this method (and the corresponding GetHashCode method), you have to maintain that contract, which is different from the IEEE behaviour.

If the Equals contract was not upheld, then the behaviour of hash tables would break.

var map = new Dictionary<double,string>();
map[double.NaN] = "NaN";
var s = map[double.NaN];

If !double.NaN.Equals(double.NaN), you'd never get your value out of the dictionary!

If the previous sentence does not make sense, then understand that the mechanics of hashing (used in Dictionary<T,U>, HashSet<T>, etc) use both the object.Equals(object) and object.GetHashCode() methods extensively, and rely upon guarantees of their behaviour.

Why does Double.NaN equal itself when wrapped in a Double instance?

What is going on is that the equals method deliberately deviates from IEE floating point. Quoting from the Javadoc for the equals(Object) method of java.lang.Double.

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 definition allows hash tables to
operate properly.

The upshot is that if you want 100% IEE floating point compatibility you need to explicitly unbox the java.lang.Double instances and compare the resulting double values.

Why is NaN not equal to NaN?

My original answer (from 4 years ago) criticizes the decision from the modern-day perspective without understanding the context in which the decision was made. As such, it doesn't answer the question.

The correct answer is given here:

NaN != NaN originated out of two pragmatic considerations:

[...] There was no isnan( ) predicate at the time that NaN was formalized in the 8087 arithmetic; 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( ) which could take many years

There was one disadvantage to that approach: it made NaN less useful in many situations unrelated to numerical computation. For example, much later when people wanted to use NaN to represent missing values and put them in hash-based containers, they couldn't do it.

If the committee foresaw future use cases, and considered them important enough, they could have gone for the more verbose !(x<x & x>x) instead of x!=x as a test for NaN. However, their focus was more pragmatic and narrow: providing the best solution for a numeric computation, and as such they saw no issue with their approach.

===

Original answer:

I am sorry, much as I appreciate the thought that went into the top-voted answer, I disagree with it. NaN does not mean "undefined" - see http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF, page 7 (search for the word "undefined"). As that document confirms, NaN is a well-defined concept.

Furthermore, IEEE approach was to follow the regular mathematics rules as much as possible, and when they couldn't, follow the rule of "least surprise" - see https://stackoverflow.com/a/1573715/336527. Any mathematical object is equal to itself, so the rules of mathematics would imply that NaN == NaN should be True. I cannot see any valid and powerful reason to deviate from such a major mathematical principle (not to mention the less important rules of trichotomy of comparison, etc.).

As a result, my conclusion is as follows.

IEEE committee members did not think this through very clearly, and made a mistake. Since very few people understood the IEEE committee approach, or cared about what exactly the standard says about NaN (to wit: most compilers' treatment of NaN violates the IEEE standard anyway), nobody raised an alarm. Hence, this mistake is now embedded in the standard. It is unlikely to be fixed, since such a fix would break a lot of existing code.

Edit: Here is one post from a very informative discussion. Note: to get an unbiased view you have to read the entire thread, as Guido takes a different view to that of some other core developers. However, Guido is not personally interested in this topic, and largely follows Tim Peters recommendation. If anyone has Tim Peters' arguments in favor of NaN != NaN, please add them in comments; they have a good chance to change my opinion.

Why float.NaN != double.NaN in C#?

NaN is never equal to NaN (even within the same type). Hence why the IsNaN function exists:

Double zero = 0;
// This will return true.
if (Double.IsNaN(0 / zero))
{
Console.WriteLine("Double.IsNan() can determine whether a value is not-a-number.");
}

You should also be aware that none of the comparisons you've shown are actually occurring "as is". When you write floatValue == doubleValue, the floats will actually be implicitly converted to doubles before the comparison occurs.

How does Double.isNaN() work?

NaN values are not equal to anything (if one side of an equality is NaN, the equality is false), so NaN != NaN. Obviously every normal double does equal itself

Equality with Double.NaN

Perhaps you are looking for the IsNaN static function?

Try something like this:

if (!Double.IsNaN(Price_Foreign))
{
output.Append(spacer);
output.Append(String.Format("{0,-10:C} USD",Price_Foreign));
}

Why are floating point infinities, unlike NaNs, equal?

Your reasoning is that Double.POSITIVE_INFINITY should not be equal to itself because it is “likely” to have been obtained as the result of a loss of accuracy.

This line of reasoning applies to all of floating-point. Any finite value can be obtained as the result of an inaccurate operation. That did not push the IEEE 754 standardization committee to define == as always evaluating to false for finite values, so why should infinities be different?

As defined, == is useful for people who understand what it does (that is, test the floating-point values that have been obtained, and certainly not the values that should have been obtained with real computations). For anyone who understands that, and you need to understand it to use floating-point even for computations that do not involve infinity, having Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY evaluate to true is convenient, if only to test if the floating-point result of a floating-point computation is Double.POSITIVE_INFINITY.

That leaves the question of why NaN can afford to have special behavior, and infinities should follow the same general principles as finite values. NaN is different from infinities: the underlying principle of the IEEE 754 standard is that values are exactly what they are, but the result of an operation can be approximated with respect to the real result, and in this case, the resulting floating-point value is obtained according to the rounding mode.

Forget for an instant that 1.0 / 0.0 is defined as +inf, which is an annoyance in this discussion. Think for the moment of Double.POSITIVE_INFINITY only as the result of operations such as 1.0e100 / 1.0e-300 or Double.MAX_VALUE + Double.MAX_VALUE. For these operations, +inf is the closest approximation of the real result, just like for operations that produce a finite result. By contrast, NaN is the result you obtain when the operation doesn't make sense. It is defensible to have NaN behave specially, but inf is just an approximation of all the values too large to represent.

In reality, 1.0 / 0.0 also produces +inf, but that should be considered an exception. It would have been just as coherent to define the result of that operation as NaN, but defining it as +inf was more convenient in the implementation of some algorithms. An example is provided page 10 in Kahan's notes. More details than most will wish for are in the article “Branch Cuts for Complex Elementary Functions, or Much Ado About Nothing's Sign Bit”. I would also interpret the existence in IEEE 754 of a “division by zero” flag separate from the NaN flag as recognition that the user may want to treat division by zero specially although it is not defined as producing NaN.

Java variable shows value of 'NaN' but var == Double.NaN is false, why?

You can check for NaN only via Double.isNan():

if (Double.isNaN(sim)) {
// is Nan
} else {
// not nan
}

On first thoughts that is not intiutive, you have to know it.
The reason behind it, is that this is specified by IEEE Floating Point standard.

You can argument:
NaN is not a number, it can be anything but not a number, so two NaN cannot be compared to be equal.

For example = 0.0 / 0.0 is NaN; and sqrt(-1) is NaN, too. But that values cannot be compared to be the same.

Additional reading: http://en.wikipedia.org/wiki/NaN



Related Topics



Leave a reply



Submit