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

ele*_*ora 12 c floating-point nan

在C中你可以测试是否使用NaN加倍isnan(x).然而,许多在线地方,包括例如这个SO答案,说你可以简单地使用x!=x.

x!=x在任何C说明书中这是保证测试,如果x为NaN的方法?我自己找不到它,我希望我的代码能够与不同的编译器一起工作.

Pas*_*uoq 9

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

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

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

这份报告描述了没有努力实现C99的编译器的黑暗时期(因为它还没有1999年,或者因为他们不够关心).

这篇2008年的文章描述了GCC如何在2008年开始实施超额精度的C99标准.在此之前,海湾合作委员会可以提供上述报告中描述的所有惊喜.

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

  • 我认为你的最后一点是关键.`x!= x`适用于IEEE 754浮点,但IEEE 754不是强制要求的.即使存在"NaN"本身也无法保证. (3认同)
  • `isnan(x)`实际上是否真的告诉你,在那些`x!= x`不能用于同一目的的平台上,`x`是否为NaN?我想象一个编译器生成两个不同的代码来计算`x`; 一个用于`isnan(x)`调用,一个用于任何你在有条件的内部使用它. (2认同)

kay*_*kay 6

请参考附录F的规范部分:IEC 60559 C标准的浮点运算:

\n
\n

F.1 简介

\n

定义的实现__STDC_IEC_559__应符合本附件中的规范。

\n

未定义的实现__STDC_IEC_559__不需要遵守这些规范。

\n
\n\n
\n

F.9.3 关系运算符

\n

如果是 a ,则表达式x \xe2\x89\xa0 x为真。xNaN

\n

如果是 a ,则表达式x = x为 false 。XNan

\n
\n\n
\n

F.3 运算符和函数

\n

isnanin<math.h>提供了isnanIEC 60559 附录中推荐的功能。

\n
\n

  • @Adam 根据我的经验,C 编译器可能会通过他们在实践中不尊重的符号的定义来声明,例如 `clang -std=c99 -mno-sse2` 声明 `FLT_EVAL_METHOD` 为零,但实际计算方式并非如此。我没想到检查它是否定义了`__STDC_IEC_559__`:http://stackoverflow.com/questions/17663780/is-there-a-document-describing-how-clang-handles-excess-floating-point- precision (3认同)