我在代码中偶然发现了.NET对double.NaN
的定义:
public const double NaN = (double)0.0 / (double)0.0;
在PositiveInfinity
和NegativeInfinity
中也是如此。
double.IsNaN
(删除一些#pragmas和注释)定义为:
[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
?
答案 0 :(得分:6)
这里的答案相当简单。 .Net框架实现了IEEE (System.Double
complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.)指定的浮点标准。这是因为浮点运算实际上必须跨多个系统工作,而不仅仅是x86 / 64架构,因此遵循这些约定可以确保兼容性问题较少(例如将代码从DSP移植到x86处理器中)。 / p>
对于d!= d,这是性能优化。基本上,该指令依赖于硬件指令,该指令可以非常快速地确定两个双浮点数是否相等。在标准下,NAN!= NAN因此是最快的测试方式。试图找到你的参考。
答案 1 :(得分:2)
为什么NaN被定义为除法 零?如何除以0 可能是双倍的,为什么NaN != NaN?
所有这些都是由IEEE 754 standard强制执行的,几乎所有现代CPU都实现了这些功能。
0.0 / 0.0如何代表“幕后”?
通过将所有位设置为1的指数和至少有一位设置为1的尾数。注意,这意味着存在大量不同的位模式,它们都代表NaN - 但是,如上所述,即使位模式相同,也必须认为它们不相等(即==必须返回false)。
答案 2 :(得分:0)
来自C#规范:
14.9.2浮点比较运算符 预定义的浮点比较运算符是:
bool operator ==(float x,float y); bool operator ==(double x,double y);
bool operator!=(float x,float y); bool operator!=(double x,double y);
bool运算符<(float x,float y); bool运算符<(double x,double y);
bool运算符>(float x,float y); bool运算符>(double x,double y);
bool运算符< =(float x,float y); bool运算符< =(double x,double y);
bool运算符&gt; =(float x,float y); bool运算符&gt; =(double x,double y);运营商根据IEC 60559标准的规则比较操作数: 如果任一操作数为NaN,则除了!=之外的所有运算符的结果都为false,结果为真。对于任何两个操作数,x!= y始终产生与!相同的结果!(x = = y)。但是,当一个或两个操作数是NaN时,&lt;,&gt;,&lt; =和&gt; =运算符不会产生与相反运算符的逻辑否定相同的结果。 [例子:如果x和y中的任何一个是NaN,那么x < y是假的,但是!(x> = y)是真的。结束例子]
关于如何在幕后呈现NaN,IEEE规范中的wikipedia article有一些例子。