如何在 ANSI C 中生成 NaN、-Infinity 和 +Infinity?

Posted

技术标签:

【中文标题】如何在 ANSI C 中生成 NaN、-Infinity 和 +Infinity?【英文标题】:How to generate NaN, -Infinity and +Infinity in ANSI C? 【发布时间】:2011-09-08 07:33:48 【问题描述】:

我使用 ANSI C89(不是 C++),我想生成 NaN-Infinity+Infinity

是否有任何标准方式(例如标准宏)? 或者是否有任何独立于平台和编译器的方式来生成这些数字?

float f = 0.0 / 0.0; // Is f ALWAYS in any platform is NaN?

【问题讨论】:

标准甚至不需要任意平台来支持 NaN 和无穷大。我相信需要一个符合 IEEE 754 的实现来支持按部门获得它们,就像你的例子一样。 【参考方案1】:

有一种创建无穷大和负无穷大的实际方法。根据 C89 遵循的 IEEE 754 标准,无穷大被定义为一个浮点数,其尾数(前 23 位)全为零,指数(后 8 位)全为 1。 nan 被定义为指数中全为 1 且尾数中除全零之外的任何数字(因为那是无穷大)。困难的部分是生成这个数字,但这可以通过以下代码完成:

unsigned int p = 0x7F800000; // 0xFF << 23
unsigned int n = 0xFF800000; // 0xFF8 << 20
unsigned int pnan = 0x7F800001; // or anything above this up to 0x7FFFFFFF
unsigned int nnan = 0xFF800001; // or anything above this up to 0xFFFFFFFF

float positiveInfinity = *(float *)&p;
float negativeInfinity = *(float *)&n;
float positiveNaN = *(float *)&pnan;
float negativeNaN = *(float *)&nnan;

但是,简单地将 unsigned 强制转换为 float 会导致编译器创建相同值的 float。所以,我们要做的就是强制编译器将内存读取为浮点数,这给了我们想要的结果。

【讨论】:

这打破了严格的别名。如果可能,请改用memcpy 或传统的除以零方法。【参考方案2】:

如果您使用不存在 INFINITY 的旧编译器,您也可以改用宏 HUGE_VAL,该宏也在 &lt;math.h&gt; 库中定义。

HUGE_VAL 应在 C89/C90 标准 (ISO/IEC 9899:1990) 中可用。

参考:http://en.cppreference.com/w/c/numeric/math/HUGE_VAL

【讨论】:

【参考方案3】:

在 C99 中有,但在以前的标准 AFAIK 中没有。

在 C99 中,您将拥有 NANINFINITY 宏。

来自“数学&lt;math.h&gt;(§7.12)部分

INFINITY 扩展为浮点类型的常量表达式,表示正或无符号无穷大(如果可用); ...

如果您被 ANSI C89 卡住,那您就倒霉了。见C-FAQ 14.9。

【讨论】:

你应该说“ANSI C89”。当前的“ANSI C”是 C99。 在 C89 中,宏 HUGE_VAL 可用于定义无穷大值。 @R..GitHubSTOPHELPINGICE ANSI 在 2000 年采用了 ISO C99。不过,目前的 C 是 ISO C18(有时是 C17)和 ANSI C18。【参考方案4】:

我不知道这是标准的还是可移植的,但这是一个开始:

jcomeau@intrepid:/tmp$ cat test.c; make test; ./test
#include <stdio.h>
int main() 
 printf("%f\n", 1.0 / 0);
 printf("%f\n", -1.0 / 0);
 printf("%f\n", 0.0 / 0);
 return 0;

cc     test.c   -o test
test.c: In function ‘main’:
test.c:3: warning: division by zero
test.c:4: warning: division by zero
test.c:5: warning: division by zero
inf
-inf
-nan

奇怪的是,我无法使用这种幼稚的方法得到正的 NaN。


另见:http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

【讨论】:

很有趣,它会产生 inf -inf nan(而不是 -nan)和 clang。不太确定-nan 应该是什么意思,实际上:-) VS2010的结果:1.#INF00 -1.#INF00 -1.#IND00 What do 1.#INF00, -1.#IND00 and -1.#IND mean? @Mat 每个浮点数总是有一个符号位。您可以通过 f | (1 &lt;&lt; 31) 获得浮点 f 的正 NaN(或任何其他数字)。 要获取-NaN,请使用-(0.f/0.f)

以上是关于如何在 ANSI C 中生成 NaN、-Infinity 和 +Infinity?的主要内容,如果未能解决你的问题,请参考以下文章

目标编码:填充扩展平均编码值中生成的 NaN

使用 Infinity 和 NaN 禁用异常

如何在字典中生成所有可能的组合

如何在C中生成随机浮点数

如何在 c++/java 中生成一组遵循特定分布的值?

如何将 pandas DataFrame 转换为省略 NaN 值的字典列表?