Why does double.IsNegative(double.NaN)
unexpectedly return true
whereas double.NaN < 0
returns false
as expected?

- 37,963
- 15
- 156
- 475

- 125
- 6
-
Note that another number that is negative, yet `n < 0` returns `false` is `-0.0`. – chux - Reinstate Monica May 21 '21 at 13:39
2 Answers
Well, according to refrence source, double.IsNegative
just checks the most significant bit:
[Pure]
[System.Security.SecuritySafeCritical] // auto-generated
internal unsafe static bool IsNegative(double d) {
return (*(UInt64*)(&d) & 0x8000000000000000) == 0x8000000000000000;
}
In case of double.NaN
the most signifucant bit is set:
11111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000
|| || |
|<- Exp -><- Mantissa ->
Sign
That's why double.IsNegative
returns true
When we put <
or >
FPU commands are used which know all ones exponent is a special kind of floating point value which should be treated in a special way.
The very same picture is with Single.NaN
.
Note, that we can construct another strange value, negative zero:
10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|| || |
|<- Exp -><- Mantissa ->
Sign
Please, look:
double negativeZero = BitConverter.ToDouble(new byte[] {
0, 0, 0, 0, 0, 0, 0, 128
});
Console.WriteLine(negativeZero == 0 ? "Zero" : "???");
Console.WriteLine(double.IsNegative(negativeZero) ? "Negative" : "???");

- 180,369
- 20
- 160
- 215
-
@harold: you quite right, thank you! Reversed image is less readable – Dmitry Bychenko May 20 '21 at 18:44
-
1Isn't it actually all-ones exponent that is special? For example all integer powers of 2 such as `1.0`, `256.0`, `0.25` have *all zeros mantissa and non-zero exponent* and they are not special. – Ben Voigt May 20 '21 at 19:58
-
@Ben Voigt: Thank you! You are absolutely right, according to IEEE-754 all ones exponent are special kind values – Dmitry Bychenko May 20 '21 at 20:08
The IEEE754 defines floating point numbers. The highest bit is used to define the sign with 0 being positive and 1 being negative.
Through a bit of digging, double.NaN
seems to be represented as 0xFFF8000000000000
in binary (and 0.0 / 0.0
in code somehow).
double.IsNegative(double d)
just checks the highest bit without any actual math being involved. Therefor, NaN is interpreted as a negative value. Meanwhile, double.NaN
if used in a binary comparison will always yield false:
double.NaN < 0.0 //false
double.NaN > 0.0 //false
double.NaN <= 0.0 //false
double.NaN >= 0.0 //false
double.NaN == 0.0 //false

- 986
- 6
- 9