Reputation: 3265
I stumbled upon .NET's definition of double.NaN
in code:
public const double NaN = (double)0.0 / (double)0.0;
This is done similarly in PositiveInfinity
and NegativeInfinity
.
double.IsNaN
(with removing a few #pragmas and comments) is defined as:
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsNaN(double d)
{
if (d != d)
{
return true;
}
else
{
return false;
}
}
This is very counter-intuitive to me.
Why is NaN defined as division by zero? How is 0.0 / 0.0
represented "behind the scenes"? How can division by 0 be possible in double
, and why does NaN != NaN
?
Upvotes: 4
Views: 355
Reputation: 346260
Why is NaN defined as division by zero? How can division by 0 be possible in double, and why does NaN != NaN?
All of these are mandated by the IEEE 754 standard, which pretty much all modern CPUs implement.
How is 0.0 / 0.0 represented "behind the scenes"?
By having an exponent with all bits set to 1 and a mantissa with at least one bit set to 1. Note that this means that there are a large number of different bit patterns that all represent NaN - but, as mentioned above, even if the bit patterns are identical, they must be considered not equal (i.e. == must return false).
Upvotes: 2
Reputation: 39325
From the C# Spec:
14.9.2 Floating-point comparison operators The predefined floating-point comparison operators are:
bool operator ==(float x, float y); bool operator ==(double x, double y);
bool operator !=(float x, float y); bool operator !=(double x, double y);
bool operator <(float x, float y); bool operator <(double x, double y);
bool operator >(float x, float y); bool operator >(double x, double y);
bool operator <=(float x, float y); bool operator <=(double x, double y);
bool operator >=(float x, float y); bool operator >=(double x, double y);The operators compare the operands according to the rules of the IEC 60559 standard: If either operand is NaN, the result is false for all operators except !=, for which the result is true. For any two operands, x != y always produces the same result as !(x == y). However, when one or both operands are NaN, the <, >, <=, and >= operators do not produce the same results as the logical negation of the opposite operator. [Example: If either of x and y is NaN, then x < y is false, but !(x >= y) is true. end example]
As to how NaN is represented behind the scenes, the wikipedia article on the IEEE spec has some examples.
Upvotes: 0
Reputation: 29322
Fairly simple answer here. .Net framework has implemented the floating point standard specified by the IEEE (System.Double
complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.). This is because floating point arithmetic actually has to work across many systems, not just x86/64 architectures, so by following the conventions this ensures that there will be less compatibility issues (for instance porting code from a DSP into an x86 processor).
As for the d != d, this is a performance optimisation. Basically this instruction relies on a hardware instruction which can very quickly determine if two double floating point numbers are equal. Under the standard, NAN != NAN and therefore is the fastest way to test. Trying to find a reference for you.
Upvotes: 6