gpt4 book ai didi

c# - 为什么 double.IsNaN 有如此奇怪的实现

转载 作者:太空狗 更新时间:2023-10-30 00:07:39 28 4
gpt4 key购买 nike

所以如果反编译.net源代码,你可以找到这段代码

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecuritySafeCritical]
[__DynamicallyInvokable]
public static unsafe bool IsNaN(double d)
{
return (ulong) (*(long*) &d & long.MaxValue) > 9218868437227405312UL;
}

所以根据 IEEE754 NaN != NaN

所以问题很简单:为什么它看起来不像

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SecuritySafeCritical]
[__DynamicallyInvokable]
public static unsafe bool IsNaN(double d)
{
return d != d;
}

我的 friend 告诉我==的实现可能是return !IsNan(this) && this.InnerEquals(other);

但是 NaN 的 afaik 实现是在处理器本身的硬件层上硬编码的。而且我们不应该单独处理 NaN 的情况。


还有一个问题。为什么这么蠢?

bool b1 = (double.NaN == double.NaN); // false
bool b2 = double.NaN.Equals(double.NaN); //true

http://ideone.com/ZSRYz1

我知道一个实现

[__DynamicallyInvokable]
public override bool Equals(object obj)
{
if (!(obj is double))
return false;
double d = (double) obj;
if (d == this)
return true;
if (double.IsNaN(d))
return double.IsNaN(this);
else
return false;
}

但不知道为什么

最佳答案

在 IEEE754 中,NaN 值被编码为具有 01 的符号位以及所有 1 位的指数部分。小数部分中的值是无关紧要的,只要它们不都是 0 位(如果是,则它是无穷大之一而不是 NaN)。

因此考虑 32 位单精度 float :

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
x 11111111 ???????????????????????

我在上面的小数位中使用了 m(尾数),以免与十六进制数字 f 混淆。

如果不是所有 ? 位都为零,则它是 NaN 编码之一。如果将其转换为 32 位长,则检查二进制文件很简单:

x 11111111 00000000000000000000000

并且,如果它大于正变体或小于负变体,那就是 NaN 编码之一。

& 操作忽略符号,因为已签名的 long.MaxValue 将为 2^63 - 1 (假设它是 64 位的)这样操作只会将最高有效位强制为 0

魔法值由 0 符号位构成,它是所有 1 位的指数(对于 double ,有 11 个,所有 分数中有 0 位。因此二进制:

seee eeee eeee mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm
0111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

给出 0x7ff00000000000009218868437227405312

关于c# - 为什么 double.IsNaN 有如此奇怪的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19832493/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com