是`x!= x`是一种可以测试NaN的便携方法吗?

时间:2015-11-25 19:25:42

标签: c floating-point nan

在C中,您可以使用isnan(x)测试是否为NaN。然而,许多在线地点,包括例如此SO answer表示您只需使用x!=x代替。

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

2 个答案:

答案 0 :(得分:9)

NaN作为唯一具有属性x的值x!=x是IEEE 754保证。无论是在C中识别NaN的忠实测试,都可以归结为变量和操作的表示与您打算使用的编译器中的IEEE 754格式和操作的紧密程度。

你应该特别担心“过度精确”以及编译器处理它的方式。当FPU仅方便地支持比编译器想要用于floatdouble类型的更广泛格式的计算时,会发生过多的精度。在这种情况下,计算可以以更宽的精度进行,并且当编译器以不可预测的方式感觉它时,可以四舍五入到类型的精度。

C99标准定义了一种处理这种超额精度的方法,该方法保留了只有NaN与其自身不同的属性,但在1999年之后很长一段时间(甚至现在编译器的作者都不在乎),如果编译器选择舍入计算的超精确结果,那么对于包含计算的有限结果的任何变量x != x,如果存在精度过高,则x可能为真。评估第一个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 iff x是NaN),或者编译器具有超标准的非标准实现,其中x != x是对NaN来说不是一个可靠的测试。

答案 1 :(得分:3)

请参阅C标准的Annex F: IEC 60559 floating-point arithmetic规范部分:

  

F.1简介

     

定义26/11/2015的实现应符合本附件中的规范。

     

未定义03/12/2015的实现不需要符合这些规范。

  

F.9.3关系运算符

     

如果__STDC_IEC_559____STDC_IEC_559__,则表达式x ≠ x为真。

     

如果xNaN,则表达式x = x为false。

  

F.3运算符和函数

     

X中的Nan宏提供了IEC 60559附录中建议的isnan功能。