如何在C中使用nan和inf?

Gra*_*oob 84 c math

如果出现错误,我有一个可以返回nan或inf的数值方法,并且为了测试目的,我想暂时强制它返回nan或inf以确保正确处理情况.是否有一种可靠的,独立编译器的方法来在C中创建nan和inf的值?

谷歌搜索大约10分钟后,我只能找到编译器相关的解决方案.

Alo*_*hal 79

您可以测试您的实现是否具有它:

#include <math.h>
#ifdef NAN
/* NAN is supported */
#endif
#ifdef INFINITY
/* INFINITY is supported */
#endif
Run Code Online (Sandbox Code Playgroud)

存在INFINITY由C99(或至少是最新的草稿)保证,并且"扩展为表示正或无符号无穷大的float类型的常量表达式,如果可用;否则为float类型的正常量,在转换时溢出."

NAN 可以定义,也可以不定义,并且"当且仅当实现支持float类型的安静NaN时才定义.它扩展为float类型的常量表达式,表示安静的NaN."

请注意,如果您要比较浮点值,请执行以下操作:

a = NAN;
Run Code Online (Sandbox Code Playgroud)

即使这样,

a == NAN;
Run Code Online (Sandbox Code Playgroud)

是假的.检查NaN的一种方法是:

#include <math.h>
if (isnan(a)) { ... }
Run Code Online (Sandbox Code Playgroud)

您还可以:a != a测试是否a为NaN.

还有isfinite(),isinf(),isnormal(),和signbit()中宏math.h在C99.

C99还具有以下nan功能:

#include <math.h>
double nan(const char *tagp);
float nanf(const char *tagp);
long double nanl(const char *tagp);
Run Code Online (Sandbox Code Playgroud)

(参考:n1256).

Docs INFINITY Docs NAN

  • 为了爱的可读性,`a!= a`应该_NEVER_使用. (20认同)
  • 很好的答案.NAN和INFINITY宏的参考是C99§7.12第4和第5段.除了(isnan(a))之外,您还可以使用(a!= a)在符合C的实现上检查NaN. (2认同)

小智 34

没有编译器独立的方法,因为C(也不是C++)标准都没有说浮点数学类型必须支持NAN或INF.

编辑:我刚检查了C++标准的措辞,它说这些函数(模板类numeric_limits的成员):

quiet_NaN() 
signalling_NaN()
Run Code Online (Sandbox Code Playgroud)

wiill返回NAN表示"如果可用".它没有扩展"如果可用"意味着什么,但可能是"如果实现的FP代表支持它们".同样,有一个功能:

infinity() 
Run Code Online (Sandbox Code Playgroud)

返回正的INF代表"如果可用".

这些都在<limits>标题中定义- 我猜测C标准有类似的东西(可能也"如果可用"),但我没有当前C99标准的副本.

  • C不强制要求IEEE浮点表示. (16认同)
  • 在C99中,C头`<math.h>`定义了`nan()`,`nanf()`和`nanl()`,它们返回NaN的不同表示形式(作为`double`,`float`,和分别使用`int`和无穷大(如果可用)可以通过生成一个带有`log(0)`或其他东西来返回.即使在C99中,也没有标准的方法来检查它们.不幸的是,`<float.h>`标题(`<limits.h>`用于整数类型)是静态的`inf`和`nan`值. (14认同)
  • @IngeHenriksen - 非常确定微软已声明它无意支持VC++支持C99. (2认同)

Aar*_*ron 20

一种独立于编译器的方式,但不是处理器独立的方式来获取这些

int inf = 0x7F800000;
return *(float*)&inf;

int nan = 0x7F800001;
return *(float*)&nan;
Run Code Online (Sandbox Code Playgroud)

这适用于任何使用IEEE 754浮点格式(x86都支持)的处理器.

更新:经过测试和更新.

  • 铸造成`(浮动&)`?这对我来说不像C.你需要`int i = 0x7F800000; return*(float*)&i;` (6认同)
  • 注意,"0x7f800001"是IEEE-754标准中所谓的*信令*NaN.虽然大多数库和硬件都不支持信令NaN,但最好还是返回一个像0x7fc00000`这样的安静NaN. (5认同)
  • **警告:**这可能会通过违反[严格别名](/ questions/98650/what-is-the-strict-aliasing-rule)规则触发**未定义行为**.建议(以及编译器中最好的支持)方式[打字](http://en.wikipedia.org/wiki/Type_punning)是通过[工会成员](/ questions/346622/views-on-type-punning) -in-C). (5认同)
  • @WaffleMatt - 为什么这个端口不会在32/64位之间?无论底层处理器的寻址大小如何,IEEE 754单精度浮点数均为32位. (2认同)
  • 除了@ulidtko指出的严格的别名问题之外,它还假定目标对整数使用相同的字节序作为浮点数,这肯定并非总是如此。 (2认同)

Tho*_* S. 20

这适用于floatdouble:

double NAN = 0.0/0.0;
double POS_INF = 1.0 /0.0;
double NEG_INF = -1.0/0.0;
Run Code Online (Sandbox Code Playgroud)

编辑:正如有人已经说过的那样,旧的IEEE标准说这些值应该会引发陷阱.但是新的编译器几乎总是关闭陷阱并返回给定的值,因为陷阱会干扰错误处理.

  • 我不知道为什么最上面的答案会出现在那里。它没有提供任何方法来生成请求的值。这个答案确实如此。 (2认同)

J.K*_*eck 12

double a_nan = strtod("NaN", NULL);
double a_inf = strtod("Inf", NULL);
Run Code Online (Sandbox Code Playgroud)

  • 这是一款智能便携式解决方案!C99需要`strtod`并确实转换NaN和Inf. (3认同)
  • 这并不是说这个解决方案有什么缺点;它们不是常数。例如,您不能使用这些值来初始化全局变量(或初始化数组)。 (3认同)
  • @马克。您始终可以拥有一个初始化函数来调用这些函数一次并将它们设置在全局命名空间中。这是一个非常可行的缺点。 (2认同)