【问题标题】:C++ Is it safe to test for NaN using cast to long? [duplicate]C++ 使用 cast to long 测试 NaN 是否安全? [复制]
【发布时间】:2014-03-07 19:57:49
【问题描述】:

据我了解,NaN 由双精度表示的指数部分中的全 1 和非零分数表示。 (来自here的信息)

使用以下方法测试 NaN 是否安全:

double num = 1.0;

// Do something to make num NaN

double* pointer = #
unsigned long long num2 = *((unsigned long long*)pointer);

if((unsigned long long)num2 == 0x7FF8000000000001)
{
    // Got a NaN
}

我希望 0x7FF8000000000001 是正确的测试。

由于小数必须为非零才能表示 NaN,所以我猜双精度表示的小数部分可以是任何东西,因此可能需要更复杂的测试,将小数部分转换为 1,如显示在数字 0x7FF8000000000001 中。 (注意末尾的 1,在小数部分。)

那么,这样的东西可以安全使用吗?

编辑:正如迈克所说,在示例中我应该使用指针来获取位,我现在将进行此更改...

【问题讨论】:

  • 有不同种类的 NAN,还有 std::isnan...
  • 该演员进行了数字转换;您需要转换引用或指针以将double 的位重新解释为整数类型。正如您所说,您需要测试该分数是否非零,不等于 1。std::isnan 将正确且可移植地测试 NaN;我就用那个。
  • Mike 提到的重要部分是std::isnan 的使用。我没有理由不使用它。
  • 是的,在 C++ 中使用 std::isnan( ),在 C 中使用 isnan( )

标签: c++ c floating-point double nan


【解决方案1】:

很多不同的 64 位位模式在浮点中表示 NaN。 Mike Seymour 告诉您使用isnan,这是检查NaN 的可读方式。您还可以使用浮点比较x != x,仅当xNaN 时才会失败。

但是,如果您坚持使用位模式:

  • 符号位无关紧要。
  • 有效位不能为零;如果是,你有一个无穷大而不是NaN
  • 偏置指数必须为0x7ff;否则,你有一个正常或次正常的浮点数。

所以我再次建议,仅当您坚持使用位模式并将自己绑定到自己的不可移植代码时,例如以下丑陋、不可移植、未经测试的 sn-p:

u64 xl = (u64 &)x;
u64 sig = xl & 0xfffffffffffffull;
if ((xl >> 52 & 0x7ff) == 0x7ff && sig != 0) return 1;
else return 0;

有效数字的高位告诉您是“安静的 NaN”还是“信号 NaN”。

【讨论】:

  • 应该避免测试x != x。一些优化编译器会将x != x 替换为false
  • @user763305:哪些编译器?因为听起来那些编译器坏了。
  • 我不记得了,但它发生在我身上。它还取决于您使用的编译器标志。
  • @user763305:是的,有时您需要解决损坏的编译器。不过,我无法想象一个以“优化”的名义故意错误编译浮点代码的编译器会让我的大部分代码工作。你确定你没有使用-ffast-math 或类似的东西?
  • 我认为它是用于 Windows 的英特尔 C++ 编译器,带有标志 -O3,最高优化级别。
猜你喜欢
  • 2012-05-04
  • 2014-03-12
  • 2014-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
  • 2013-08-11
相关资源
最近更新 更多