So if decompile .net sources, you can find this code
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecuritySafeCritical]
[__DynamicallyInvokable]
public static unsafe bool IsNaN(double d)
{
return (ulong) (*(long*) &d & long.MaxValue) > 9218868437227405312UL;
}
so according to IEEE754 NaN != NaN
So question is simple: why it doesn't look like
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecuritySafeCritical]
[__DynamicallyInvokable]
public static unsafe bool IsNaN(double d)
{
return d != d;
}
My friend told me that implementation of ==
may be return !IsNan(this) && this.InnerEquals(other);
but afaik implementation of NaN is hard-coded on hardware layer, in processor itself. And we shouldn't process NaN
case separately.
And one more question. Why it's so stupid?
bool b1 = (double.NaN == double.NaN); // false
bool b2 = double.NaN.Equals(double.NaN); //true
http://ideone.com/ZSRYz1
i know an implementation
[__DynamicallyInvokable]
public override bool Equals(object obj)
{
if (!(obj is double))
return false;
double d = (double) obj;
if (d == this)
return true;
if (double.IsNaN(d))
return double.IsNaN(this);
else
return false;
}
but dunno WHY
In IEEE754, a NaN value is encoded having a sign bit of 0
or 1
and an exponent section of all 1
bits. The value in the fraction section is irrelevant as long as they're not all 0
bits (if they are, it's one of the infinities rather than NaN).
Hence consider the 32-bit single precision float:
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
x 11111111 ???????????????????????
I've used m
(for mantissa) for the fraction bits above so as not to confuse it with the hex digit f
.
Provided not all of those ?
bits are zero, it's one of the NaN encodings. If you cast that to a 32-bit long, it's a simple matter to check against binary:
x 11111111 00000000000000000000000
and, if it's larger than the positive variant or less than the negative variant , that's one of the NaN encodings.
It's the ignoring of the sign that's being done by the &
operation since the signed long.MaxValue
will be 2^63 - 1
(assuming it's 64-bit) so that operation will simply force the most significant bit to 0
.
The magic value is constructed from a 0
sign bit, an exponent of all 1
bits (for double precision, there are eleven of these, and all 0
bits in the fraction. Hence binary:
seee eeee eeee mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm
0111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
gives 0x7ff0000000000000
or 9218868437227405312
.
Hard to be sure without being the implementor, but my guess is that the designers considered signaling NaNs (SNAN). If exceptions are unmasked then testing for equality on an SNAN will raise a hardware floating point exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With