【问题标题】:What is the most correct way to compare float to a specific NAN value?将浮点数与特定 NAN 值进行比较的最正确方法是什么?
【发布时间】:2014-11-26 00:02:35
【问题描述】:

NaN 可能具有许多不同的二进制表示,它们通常可用于提供有关导致 NaN 的原因的更多信息。 x111 1111 1xxx xxxx xxxx xxxx xxxx xxxx 格式的任何 IEEE 32 位浮点数都是 NaN。此外,2 个 NaN(可能具有不同的二进制值)之间的任何比较都会评估为假。

所以给定两个浮点数:

float a = NaN1;
float b = NaN2;

两者都是 NaN,但上面的 x 位可能有不同的值,比较它们的二进制内容的最正确方法是什么(即检查它们是否与 NaN 的 type 相同) ?

对我来说最明显的方法是执行 c 风格的转换,例如:*(uint32_t*)&a == *(uint32_t*)&b 然而,浮点数的大小不能保证为 32 位。

【问题讨论】:

  • 浮点到整数的转换:stackoverflow.com/questions/2544394/…
  • 您希望遇到哪些支持 NaN 的非 32 位大小的浮点数?我认为您不太可能在实践中遇到任何支持 NaN 的非 IEEE 754 格式。我想float 可能是 64 位 IEEE 754 双精度类型,虽然这有点不正常。
  • @MarkDickinson 这是嵌入式应用程序的代码。我的主要目标是 Raspberry Pi,但我的目标是支持任何带有 c 编译器的半强大微控制器。遇到 16 位半精度浮点型我完全不会感到惊讶。我无法想象在未来十年内默认浮点数不会是 16、32 或 64 位的架构,但我更愿意在实际情况下避免不必要的限制。
  • 啊,是的,16 位就可以了。谢谢。
  • 根据严格的别名规则,将指针投射到 uint32_t * 是 UB。 mmecmp,正如回答者所说,是要走的路。

标签: c++ floating-point equality ieee-754


【解决方案1】:

我猜第二个最明显的就是使用memcmp(),这是比较两个内存块逐位比较的标准函数:

const bool equal = memcmp(&a, &b, sizeof a) == 0;

此外,正如评论中所建议的,最好验证尺寸是否相同:

const bool equal = (sizeof a == sizeof b) && (memcmp(&a, &b, sizeof a) == 0);

我不确定在这里使用 static_assert() 是否会赢,但我也不是 C++11 专家。

【讨论】:

  • 由于这是C++,你可以添加一个static_assert(sizeof(a) == sizeof(b))
  • 看起来有点矫枉过正,但它应该可以解决所有可移植性问题。我想知道现代 gcc 是否能够在 sizeof(float)
  • @Wallacoloo 它能够做到这一点。 memcmp 是我所知道的所有主要编译器的内在属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 1970-01-01
  • 2017-08-01
  • 2013-11-19
相关资源
最近更新 更多