double.NaN - 这个违反直觉的功能是如何工作的?
Posted
技术标签:
【中文标题】double.NaN - 这个违反直觉的功能是如何工作的?【英文标题】:double.NaN - how does this counterintuitive feature work? 【发布时间】:2011-05-30 16:57:04 【问题描述】:我偶然发现了 .NET 在代码中对double.NaN
的定义:
public const double NaN = (double)0.0 / (double)0.0;
PositiveInfinity
和 NegativeInfinity
的做法类似。
double.IsNaN
(去掉一些#pragmas 和 cmets)定义为:
[Pure]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsNaN(double d)
if (d != d)
return true;
else
return false;
这对我来说非常违反直觉。
为什么将 NaN 定义为除以零? 0.0 / 0.0
如何代表“幕后”? double
怎么能被0除,为什么NaN != NaN
会这样?
【问题讨论】:
这更多是关于 NaN 而不是 .NET 的细节......请参阅 en.wikipedia.org/wiki/NaN double.NaN 的可能副本 @Jon Skeet:我同意,感谢您指出这一点并提供链接!稍微改变了问题,减少了 .NET 的特定性。 它与 database-null 兼容。还有一条规则说 null != null 【参考方案1】:这里的答案很简单。 .Net 框架实现了 IEEE (System.Double
complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.) 指定的浮点标准。这是因为浮点运算实际上必须在许多系统上工作,而不仅仅是 x86/64 架构,因此通过遵循约定可以确保更少的兼容性问题(例如将代码从 DSP 移植到 x86 处理器)。
至于 d != d,这是一个性能优化。基本上,这条指令依赖于一个硬件指令,它可以非常快速地确定两个双浮点数是否相等。根据标准,NAN != NAN 因此是最快的测试方式。正在为您寻找参考。
【讨论】:
我不认为这是性能优化。相反,这是测试 NaN 的标准(并且可能是唯一可移植的)方法,根据定义起作用。【参考方案2】:为什么将 NaN 定义为除以 零?怎么能除以0 可能是双倍的,为什么 NaN != NaN?
所有这些都由IEEE 754 standard 强制执行,几乎所有现代 CPU 都实现了。
0.0 / 0.0 如何在“幕后”表示?
通过将所有位设置为 1 的指数和至少一位设置为 1 的尾数设置。请注意,这意味着有大量不同的位模式都表示 NaN - 但是,如上所述,即使位模式相同,它们也必须被视为不相等(即 == 必须返回 false)。
【讨论】:
【参考方案3】:来自 C# 规范:
14.9.2 浮点比较运算符 预定义的浮点比较运算符有:
布尔运算符 ==(float x, float y);布尔运算符 ==(double x, double y); 布尔运算符 !=(float x, float y);布尔运算符 !=(double x, double y); 布尔运算符 布尔运算符 >(float x, float y);布尔运算符 >(double x, double y); 布尔运算符 布尔运算符 >=(float x, float y);布尔运算符 >=(double x, double y);
运算符根据 IEC 60559 标准的规则比较操作数: 如果任一操作数为 NaN,则除 != 以外的所有运算符的结果均为假,结果为真。 对于任何两个操作数,x != y 始终产生与 !(x = = y)。但是,当一个或两个操作数都是 NaN 时,、= 运算符不会产生与相反运算符的逻辑否定相同的结果。 [示例:如果 x 和 y 中的任何一个为 NaN,则 x = y) 为真。结束示例]
关于 NaN 在幕后是如何表示的,IEEE 规范中的 wikipedia article 有一些例子。
【讨论】:
以上是关于double.NaN - 这个违反直觉的功能是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章
Javascript (ECMAScript5) 的细节和违反直觉的地方
Javascript (ECMAScript5) 的细节和违反直觉的地方
为啥 Double.NaN==Double.NaN 返回 false?
如何在 C# 中处理接受 IComparable 的通用方法的 double.NaN