double.NaN 和 double.NegativeInfinity 的 CompareTo 行为

Posted

技术标签:

【中文标题】double.NaN 和 double.NegativeInfinity 的 CompareTo 行为【英文标题】:CompareTo behaviour for double.NaN and double.NegativeInfinity 【发布时间】:2013-01-04 22:16:49 【问题描述】:

我在 C# (.Net 4) 中使用 double[] 进行一些统计操作,然后我发现使用 CompareTo 方法和 double.NaN 的一些奇怪行为。当我尝试这段代码时:

double.NaN.CompareTo(double.NegativeInfinity) //returns -1

这意味着double.NaNdouble.NegativeInfinity 还要小!谁能解释一下为什么会这样?

【问题讨论】:

那么你的问题是什么? 不,这意味着对于排序的情况,NaN被认为小于负无穷大。我冒昧地猜测,在将 NegativeInfinity 与 null 进行比较时遵循相同的规则。 除了“这就是规范所说的那样”或者可能是一些疯狂的猜测之外,您不太可能得到任何答案。 【参考方案1】:

CompareTo 不会告诉您一件事比另一件事小。它告诉您在订购实例时一个实例在 (-) 之前、在 (+) 之后或可与 (0) 另一个实例互换。

这里的为什么实际上取决于那些在 CLR 中为原语设计行为的人。

IComparable 的目的是对一个类型的实例进行排序。因此,对于 NaN,一个有效的 double 值,决定将其排序该类型的任何其他实例之前。

请注意,CompareTo 在含义或预期用途上不一定与数字大于/小于操作相同。 CompareTo 旨在为 double 可以采用的一组值提供排序。例如,

double.NaN.CompareTo(double.NaN)

将返回 0。但是

double.NaN == double.NaN

是假的。同样,

double.NaN.CompareTo(double.NegativeInfinity)

返回-1,但是

double.NaN < double.NegativeInfinity

返回假。因此,CompareTo 方法并不是说在数学上 double.NaN 小于 double.NegativeInfinity。小于运算符实际上说这不是真的。但它是说,在排序值时, double.NaN 排在第一位。

这里也是 Double 类型的 LessThan Operator 文档的链接。并排阅读它以及IComparable.CompareTo 的含义应该有助于阐明这两种方法试图表达的差异。

【讨论】:

【参考方案2】:

double.NaN 小于负无穷大。

来自他们解释的元数据信息;

public const double NegativeInfinity = -1.0 / 0.0

public const double NaN = 0.0 / 0.0;

来自Double.CompareTo()方法;

将此实例与指定的双精度浮点数进行比较 number 并返回一个整数,表示 this 的值是否 实例小于、等于或大于 指定的双精度浮点数。

如果这个实例不是一个数字(NaN)并且值是一个数字

Double.CompareTo() 方法返回一个负整数

让我们看看这个示例(这里是一个DEMO);

void Main()

    double a = double.NaN;
    double b = double.NegativeInfinity;
    Console.WriteLine(a.CompareTo(b));

即使我们查看 IL 代码,double.NaN 也代表 00 00 00 00 00 00 F8 FFdouble.NegativeInfinity 代表 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

【讨论】:

呵呵 MSDN 不正确:Double.NaN.CompareTo(double.NaN) 返回 0,而不是 -1。 幸运。 :-) 好吧,我承认,当它们都是 NaN 时,MSDN 告诉它是 0。 @StefandeBruijn MSDN 是对的。它说 此实例和值都不是数字 (NaN)、PositiveInfinity 或 NegativeInfinity。它返回零。所以我认为 MSDN 是正确的。 是的,我首先阅读了您不完整信息的答案,然后在 MSDN 上看到了它。你只是对我来说编辑得太快了;-)【参考方案3】:

归根结底,将 double.nan 在数字上与任何东西进行比较是没有意义的。但是,如果你有一个 double 列表并想用它做点什么,你会希望它们都在列表的末尾,这样你就可以先做所有有意义的工作,这样当你看到第一个时你就可以停下来。这就像一个列表,其中一些项目为空,它们被推到最后。

出现double.nan的几种情况:

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

【讨论】:

以上是关于double.NaN 和 double.NegativeInfinity 的 CompareTo 行为的主要内容,如果未能解决你的问题,请参考以下文章

比较 Scala 和 Java Double.NaN

为啥 Double.NaN==Double.NaN 返回 false?

double.NaN - 这个违反直觉的功能是如何工作的?

与 Double.NaN 相等

将 Double.NaN 与自身进行比较

Scala Spark 在数据帧和数据集中以不同方式处理 Double.NaN