c - `x!=x` 是测试 NaN 的可移植方法吗?

标签 c floating-point nan

在 C 中,您可以使用 isnan(x) 测试 double 是否为 NaN。但是网上有很多地方,例如这个 SO answer假设您可以简单地使用 x!=x 代替。

x!=x 在任何 C 规范中是否作为保证测试 x 是否为 NaN 的方法?我自己找不到它,我希望我的代码能够与不同的编译器一起工作。

最佳答案

NaN 作为唯一值 x 具有属性 x!=x 是 IEEE 754 保证。识别 C 中的 NaN 是否是一个忠实的测试,归结为变量的表示和操作与您打算使用的编译器中的 IEEE 754 格式和操作的映射有多紧密。

您应该特别担心“超精度”以及编译器处理它的方式。当 FPU 仅方便地支持比编译器希望用于 floatdouble 类型的更宽格式的计算时,就会出现精度过高的情况。在这种情况下,可以以更宽的精度进行计算,并在编译器以不可预测的方式进行调整时四舍五入到类型的精度。

C99 标准定义了一种处理这种超额精度的方法,该方法保留了只有 NaN 与自身不同的属性,但在 1999 年之后的很长一段时间内(甚至在编译器作者不关心的今天),存在超额精度精度,如果编译器选择舍入第一个 x 和第二个 x 之间的计算。

report描述了没有努力实现 C99 的编译器的黑暗时期(要么是因为还不是 1999 年,要么是因为他们不够关心)。

2008 post描述了 GCC 如何在 2008 年开始实现 C99 超精度标准。在此之前,GCC 可以提供上述报告中描述的所有惊喜。

当然,如果目标平台根本不实现 IEEE 754,则 NaN 值甚至可能不存在,或者存在并且具有与 IEEE 754 指定的不同的属性。常见情况是非常忠实地实现 IEEE 754 的编译器FLT_EVAL_METHOD 设置为 0、1 或 2(所有这些都保证 x != x 当且仅当 x 为 NaN),或者编译器具有非标准的 excess 实现精度,其中 x != x 不是 NaN 的可靠测试。

关于c - `x!=x` 是测试 NaN 的可移植方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33924866/

相关文章:

C:我不断收到错误消息:预期表达式

c - 以下代码段中动态分配了多少字节?

ios - 如何在iOS中将浮点值格式化为小数点后只有2位?

nan - tensorflow NaN 错误?

C++ 卡尔曼滤波器库产生 1.#R(NaN) 结果

c - 将节点放入不应该存在的解析树中

Java float 说明

python - 检查Python中的 float 是否正常

javascript - 从链接的输入字段中删除文本时删除 NaN

c - 避免内联 c 中无效的初始化程序