C 这是'x=x`NaN的便携式测试方法?

C 这是'x=x`NaN的便携式测试方法?,c,floating-point,nan,C,Floating Point,Nan,在C语言中,您可以使用isnan(x)测试双if-NaN。然而,许多在线的地方,包括例如这个地方,都说你可以简单地使用x=x 是x=x在任何C规范中作为一种保证测试x是否为NaN的方法?我自己找不到它,我希望我的代码可以与不同的编译器一起工作。NaN是唯一一个属性为x的值x=x是IEEE 754的保证。在C语言中识别NaN是否是一个可靠的测试,归根结底是变量的表示和操作映射到IEEE 754格式以及您打算使用的编译器中的操作的紧密程度 您应该特别担心“精度过高”以及编译器处理它的方式。当FPU仅

在C语言中,您可以使用
isnan(x)
测试双if-NaN。然而,许多在线的地方,包括例如这个地方,都说你可以简单地使用
x=x


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

NaN是唯一一个属性为
x的值
x
=x
是IEEE 754的保证。在C语言中识别
NaN
是否是一个可靠的测试,归根结底是变量的表示和操作映射到IEEE 754格式以及您打算使用的编译器中的操作的紧密程度

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

C99标准定义了一种处理这种超精度的方法,它保留了只有NaN与自身不同的属性,但在1999年之后的很长一段时间内(甚至在编译器的作者不关心的今天),在存在超精度的情况下,
x!=如果编译器选择在计算第一个
x
和第二个
x
之间对计算的超精度结果进行四舍五入,则对于包含有限计算结果的任何变量
x
,x
可能为真

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

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


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

请参考C标准的规范部分:

F.1导言 定义
\uu STDC\u IEC\u 559\uuu
的实施应符合本附录中的规范

不定义
\uuuu STDC\u IEC\uu559\uuuu
的实施不需要符合这些规范

F.9.3关系运算符 表达式
x≠ 如果
x
NaN
,则x
为真

如果
x
Nan
,则表达式
x=x
为false

F.3操作员和功能
中的
isnan
宏提供了IEC 60559附录中推荐的
isnan
功能


我认为你的最后一点是关键<代码>x!=x适用于IEEE 754浮点,但IEEE 754不是强制性的。即使
NaN
本身的存在也不能保证。在
x!=x不适用于相同的用途?我想象一个编译器生成两段不同的代码来计算
x
;一个用于
isnan(x)
调用,另一个用于在该条件中使用它的任何东西。换句话说,是否有一个程序使用folliowing函数
f
,当使用这种编译器构建时,会导致
f
打印出“0是NaN”,然后运行<代码>空格f(double x){if(x!= x)打印(“%f是南\n”);} /Cord:DO实现实际上定义了< C++ > SydCdCIECIE599X<<代码>,或者它是编译器不想声明为兼容的C++版本吗?@亚当,有效的问题!gcc 5.2.1 20151028对其进行了定义,而clang 3.5.2-3未对其进行定义。对于x86_64-pc-linux-gnu目标,也就是说。@Adam在我的经验中,C编译器可能通过定义他们在实践中不尊重的符号来声明,例如
clang-std=c99-mno-sse2
声明
FLT_EVAL_方法
在实际计算时为零。我没想过要检查它是否定义了
\uu STDC\u IEC\u 559\uuuu
:您是否仍在试图找到优化
isnan()
的方法?您是否真的对应用程序进行了基准测试并发现这是瓶颈?