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

发布于 2024-10-09 07:56:09 字数 856 浏览 5 评论 0原文

我偶然发现了 .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

I stumbled upon .NET's definition of double.NaN in code:

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

This is done similarly in PositiveInfinity and NegativeInfinity.

double.IsNaN (with removing a few #pragmas and comments) is defined as:

[Pure] 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsNaN(double d) 
{
    if (d != d)
    { 
        return true; 
    }
    else 
    {
        return false;
    }
}

This is very counter-intuitive to me.

Why is NaN defined as division by zero? How is 0.0 / 0.0 represented "behind the scenes"? How can division by 0 be possible in double, and why does NaN != NaN?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不打扰别人 2024-10-16 07:56:09

这里的答案相当简单。 .Net框架实现了IEEE (System.Double 符合二进制浮点运算的 IEC 60559:1989 (IEEE 754) 标准。)。这是因为浮点运算实际上必须在许多系统上工作,而不仅仅是 x86/64 架构,因此通过遵循约定,可以确保减少兼容性问题(例如将代码从 DSP 移植到 x86 处理器)。

至于d != d,这是一个性能优化。基本上,该指令依赖于硬件指令,该指令可以非常快速地确定两个双浮点数是否相等。根据标准,NAN != NAN 因此是最快的测试方法。试图为您找到一个参考。

Fairly simple answer here. .Net framework has implemented the floating point standard specified by the IEEE (System.Double complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.). This is because floating point arithmetic actually has to work across many systems, not just x86/64 architectures, so by following the conventions this ensures that there will be less compatibility issues (for instance porting code from a DSP into an x86 processor).

As for the d != d, this is a performance optimisation. Basically this instruction relies on a hardware instruction which can very quickly determine if two double floating point numbers are equal. Under the standard, NAN != NAN and therefore is the fastest way to test. Trying to find a reference for you.

姐不稀罕 2024-10-16 07:56:09

为什么 NaN 被定义为除以
零?除以0怎么可能
可能是 double,为什么 NaN
!= NaN?

所有这些都是由 IEEE 754 标准强制执行的,几乎所有现代 CPU 都实施该标准。

0.0 / 0.0 在“幕后”是如何表示的?

通过将所有位设置为 1 的指数和至少一位设置为 1 的尾数。请注意,这意味着有大量不同的位模式都表示 NaN - 但是,如上所述,即使位模式相同,必须将它们视为不相等(即 == 必须返回 false)。

Why is NaN defined as division by
zero? How can division by 0 be
possible in double, and why does NaN
!= NaN?

All of these are mandated by the IEEE 754 standard, which pretty much all modern CPUs implement.

How is 0.0 / 0.0 represented "behind the scenes"?

By having an exponent with all bits set to 1 and a mantissa with at least one bit set to 1. Note that this means that there are a large number of different bit patterns that all represent NaN - but, as mentioned above, even if the bit patterns are identical, they must be considered not equal (i.e. == must return false).

萌︼了一个春 2024-10-16 07:56:09

来自 C# 规范:

14.9.2 浮点比较运算符
预定义的浮点比较运算符是:

<块引用>

布尔运算符 ==(float x, float y);布尔运算符 ==(double x, double y);
布尔运算符 !=(浮点数 x, 浮点数 y);布尔运算符 !=(double x, double y);
布尔运算符 <(float x, float y);布尔运算符 <(双 x, 双 y);
布尔运算符>(浮点x,浮点y);布尔运算符 >(双 x, 双 y);
布尔运算符 <=(float x, float y);布尔运算符 <=(double x, double y);
布尔运算符>=(浮点x,浮点y);布尔运算符 >=(double x, double y);

运算符根据 IEC 60559 标准的规则比较操作数:
如果任一操作数为 NaN,则除 != 之外的所有运算符的结果均为 false,而 != 的结果为 true。对于任何两个操作数,x != y 始终生成与 !(x = 相同的结果= y)。然而,当一个或两个操作数均为 NaN 时,<、>、<= 和 >= 运算符不会产生与相反运算符的逻辑非相同的结果。 [示例:如果 x 和 y 中的任何一个为 NaN,则 x < y 为假,但 !(x >= y) 为真。示例结束]

至于 NaN 在幕后如何表示,请参考 IEEE 的 wikipedia 文章规范有一些例子。

From the C# Spec:

14.9.2 Floating-point comparison operators
The predefined floating-point comparison operators are:

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 operator <(float x, float y); bool operator <(double x, double y);
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 operator >=(float x, float y); bool operator >=(double x, double y);

The operators compare the operands according to the rules of the IEC 60559 standard:
If either operand is NaN, the result is false for all operators except !=, for which the result is true. For any two operands, x != y always produces the same result as !(x == y). However, when one or both operands are NaN, the <, >, <=, and >= operators do not produce the same results as the logical negation of the opposite operator. [Example: If either of x and y is NaN, then x < y is false, but !(x >= y) is true. end example]

As to how NaN is represented behind the scenes, the wikipedia article on the IEEE spec has some examples.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文