4

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

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

所以根据 IEEE754NaN != NaN

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

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

我的朋友告诉我,实施==可能是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;
}

但不知道为什么

4

2 回答 2

9

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

因此考虑 32 位单精度浮点数:

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

我已将m(尾数)用于上面的小数位,以免将其与 hex digit 混淆f

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

x 11111111 00000000000000000000000

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

这是忽略&操作正在执行的符号,因为有符号long.MaxValue将是2^63 - 1(假设它是 64 位),因此该操作将简单地将最高有效位强制为0.

魔术值是由一个0符号位构成的,所有位的指数1(对于双精度,有 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

于 2013-11-07T09:45:54.053 回答
4

如果不是实现者,很难确定,但我的猜测是设计者考虑了信号 NaN(SNAN)。如果异常未屏蔽,则在 SNAN 上测试相等性将引发硬件浮点异常。

于 2013-11-07T10:02:33.260 回答