如何在C中使用nan和inf?
我有一个数值方法,如果出现错误,可以返回nan或inf,为了testing目的,我想暂时强制它返回nan或inf,以确保正确处理情况。 有没有一种可靠的, 独立于编译器的方法来创buildC中nan和inf的值?
谷歌search了大约10分钟后,我只能find依赖于编译器的解决scheme。
你可以testing你的实现是否有:
#include <math.h> #ifdef NAN /* NAN is supported */ #endif #ifdef INFINITY /* INFINITY is supported */ #endif
INFINITY
的存在由C99(或至less是最新的草案)保证,并且“扩展为浮点types(表示正或无符号无穷大(如果可用))的常量expression式;否则,在翻译时溢出的floattypes的正常数。 “
NAN
可以被定义,也可以不被定义,并且“当且仅当该实现支持浮点types的安静NaN时才被定义,并且扩展为代表安静的NaN的floattypes的常量expression式。
请注意,如果您正在比较浮点值,请执行以下操作:
a = NAN;
即使这样,
a == NAN;
是错误的。 检查NaN的一种方法是:
#include <math.h> if (isnan(a)) { ... }
你也可以这样做: a != a
来testinga
是否是NaN。
在C99的math.h
中还有isfinite()
, isfinite()
, isinf()
和signbit()
macros。
C99也有nan
function:
#include <math.h> double nan(const char *tagp); float nanf(const char *tagp); long double nanl(ocnst char *tagp);
(参考:n1256)。
这样做没有编译器独立的方式,因为C(也就是C ++)标准都没有说浮点mathtypes必须支持NAN或INF。
编辑:我刚刚检查了C ++标准的措辞,它说这些函数(模板类numeric_limits的成员):
quiet_NaN() signalling_NaN()
将返回NAN表示“如果可用”。 它并没有扩展“如果可用”的意思,但大概是“如果实施的FP rep支持他们”的东西。 同样,还有一个function:
infinity()
这将返回一个正面的INF代表“如果可用”。
这些都在<limits>
头文件中定义 – 我猜测C标准有类似的东西(可能也是“如果可用”),但是我没有C99标准的副本。
独立于编译器的方式,而不是处理器独立的方式来获取这些:
int inf = 0x7F800000; return *(float*)&inf; int nan = 0x7F800001; return *(float*)&nan;
这应该在任何使用IEEE 754浮点格式的处理器上工作(x86是这样的)。
更新:testing和更新。
这适用于float
和double
:
double NAN = 0.0/0.0; double POS_INF = 1.0 /0.0; double NEG_INF = -1.0/0.0;
编辑:正如有人已经说过,旧的IEEE标准说,这样的价值应该提高陷阱。 但是新编译器几乎总是closures陷阱并返回给定的值,因为陷阱干扰了error handling。
double a_nan = strtod("NaN", NULL); double a_inf = strtod("Inf", NULL);
<inf.h> /* IEEE positive infinity. */ #if __GNUC_PREREQ(3,3) # define INFINITY (__builtin_inff()) #else # define INFINITY HUGE_VALF #endif
和
<bits/nan.h> #ifndef _MATH_H # error "Never use <bits/nan.h> directly; include <math.h> instead." #endif /* IEEE Not A Number. */ #if __GNUC_PREREQ(3,3) # define NAN (__builtin_nanf ("")) #elif defined __GNUC__ # define NAN \ (__extension__ \ ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; }) \ { __l: 0x7fc00000UL }).__d) #else # include <endian.h> # if __BYTE_ORDER == __BIG_ENDIAN # define __nan_bytes { 0x7f, 0xc0, 0, 0 } # endif # if __BYTE_ORDER == __LITTLE_ENDIAN # define __nan_bytes { 0, 0, 0xc0, 0x7f } # endif static union { unsigned char __c[4]; float __d; } __nan_union __attribute_used__ = { __nan_bytes }; # define NAN (__nan_union.__d) #endif /* GCC. */
我也惊讶这些不是编译时间常量。 但是我想你可以通过简单地执行返回这样一个无效结果的指令来轻松创build这些值。 除以0,0的对数,90的tan,那种事情。
我通常使用
#define INFINITY (1e999)
要么
const double INFINITY = 1e999
至less在IEEE 754环境中起作用,因为最高可表示的double值大约是1e308
。 1e309
就像1e99999
年1月9日那样1e99999
,但是三个9就足够了,令人难忘。 既然这是一个双重字符(在#define
情况下)或一个实际的Inf
值,即使你使用128位(“长双”)浮点数,它仍然是无限的。