Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top