double.NaN - 这种违反直觉的功能如何运作?

时间:2010-12-25 19:39:29

标签: double nan

我在代码中偶然发现了.NET对double.NaN的定义:

public const double NaN = (double)0.0 / (double)0.0;

PositiveInfinityNegativeInfinity中也是如此。

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

3 个答案:

答案 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运算符> =(float x,float y); bool运算符> =(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有一些例子。