C 这是'x=x`NaN的便携式测试方法?
在C语言中,您可以使用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仅
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
iffx
为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()
的方法?您是否真的对应用程序进行了基准测试并发现这是瓶颈?