Reputation: 32481
I was doing some statistical operations in C# (.Net 4) with double[]
then i found some strange behavior with CompareTo
method and double.NaN
. when I try this code:
double.NaN.CompareTo(double.NegativeInfinity) //returns -1
It means double.NaN
is even smaller than double.NegativeInfinity
! can anyone explain why it is like this?
Upvotes: 5
Views: 2982
Reputation: 5107
At the end of the day, comparing double.nan numerically to anything is meaningless. But if you have a list of double and want to do something with it, you'd want them all at the end of the list so that you can do all meaningful work first and so that you can stop when you see the first one. It's like a list where some items are null, they get shoved to the end.
A few cases where double.nan occurs:
Dim d1 as double = 0/0
Dim d2 as double = Double.PositiveInfinity / Double.PositiveInfinity
Dim d3 as double = Double.PositiveInfinity / Double.NegativeInfinity
Dim d4 as double = Double.PositiveInfinity / Double.PositiveInfinity
Dim d5 as double = Double.PositiveInfinity / Double.NegativeInfinity
Upvotes: 0
Reputation: 1125
CompareTo does not tell you that one thing is smaller than another. It tells you one instance precedes (-), follows (+) or is interchangeable with (0) another instance when ordering instances.
The why here is really up to those designing behavior for primitives in the CLR.
IComparable's purpose is for ordering instances of a type. So for NaN, a valid double value, the decision was made to order it before any other instance of the type.
Note that CompareTo is not necessarily the same, in meaning, or in intended use, as numeric greater than/less than operations. CompareTo is meant to provide an ordering over the set of values that double can take on. For example,
double.NaN.CompareTo(double.NaN)
will return 0. But
double.NaN == double.NaN
is false. Likewise,
double.NaN.CompareTo(double.NegativeInfinity)
returns -1, but
double.NaN < double.NegativeInfinity
returns false. So, the CompareTo method is not saying that mathematically double.NaN is smaller than double.NegativeInfinity. The less than operator in fact says that's not true. But it is saying that, when ordering values, double.NaN comes first.
Here is a link to the Double type's LessThan Operator documentation as well. Reading that as well as the meaning of IComparable.CompareTo side by side should help clarify the difference in what the two methods are trying to express.
Upvotes: 7
Reputation: 98740
double.NaN
is less than negative infinity.
From metadata information they explained like;
public const double NegativeInfinity = -1.0 / 0.0
public const double NaN = 0.0 / 0.0;
From Double.CompareTo()
method;
Compares this instance to a specified double-precision floating-point number and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified double-precision floating-point number.
If This instance is not a number (NaN) and value is a number
Double.CompareTo()
method returns A negative integer
Let's look at this sample (here is a DEMO
);
void Main()
{
double a = double.NaN;
double b = double.NegativeInfinity;
Console.WriteLine(a.CompareTo(b));
}
Even when we look at IL code, double.NaN
represents with 00 00 00 00 00 00 F8 FF
and double.NegativeInfinity
represents with 00 00 00 00 00 00 F0 FF
;
IL_0000: ldc.r8 00 00 00 00 00 00 F8 FF
IL_0009: stloc.0
IL_000A: ldc.r8 00 00 00 00 00 00 F0 FF
IL_0013: stloc.1
IL_0014: ldloca.s 00
IL_0016: ldloc.1
IL_0017: call System.Double.CompareTo
IL_001C: call System.Console.WriteLine
Upvotes: 8