How to use nan and inf in C?

I have a numerical method that could return nan or inf if there was an error, and for testing, I would like to temporarily force it to return nan or inf to ensure that the situation is handled correctly. Is there a reliable compiler-independent way to create nan and inf values ​​in C?

After googling for about 10 minutes, I was able to find compiler dependent solutions.

+68
c math
Dec 17 '09 at 18:57
source share
8 answers

You can check if your implementation has:

#include <math.h> #ifdef NAN /* NAN is supported */ #endif #ifdef INFINITY /* INFINITY is supported */ #endif 

The existence of INFINITY guaranteed by C99 (or at least by the last draft), and "expands to a constant expression of type float representing positive or unsigned infinity, if any; else to a positive constant of type float that overflows during translation."

NAN may or may not be defined, and "is defined if and only if the implementation supports silent NaNs for the float type. It expands to a constant expression of the float type, which is a calm NaN."

Note that if you compare floating point values ​​and do:

 a = NAN; 

even then,

 a == NAN; 

is false. One way to check NaN:

 #include <math.h> if (isnan(a)) { ... } 

You can also do: a != a to check if a NaN.

C99 also has isfinite() , isinf() , isnormal() and signbit() macros in isfinite()

C99 also has NAN features:

 #include <math.h> double nan(const char *tagp); float nanf(const char *tagp); long double nanl(ocnst char *tagp); 

(Ref: n1256).

+66
Dec 17 '09 at 19:15
source share

There is no compiler-independent way to do this, since neither the C (and C ++) standards say that floating-point math types must support NAN or INF.

Edit: I just checked the wording of the C ++ standard, and it says that these functions (members of the template class numeric_limits):

 quiet_NaN() signalling_NaN() 

will return NAN views "if available". It does not extend what “if available” means, but it seems to be something like “if FP rep support supports them”. Similarly, there is a function:

 infinity() 

which returns a positive INF rep "if available".

They are both defined in the <limits> header - I would suggest that the C standard has something similar (maybe also "if available"), but I don't have a copy of the current C99 standard.

+33
Dec 17 '09 at 19:00
source share

A compiler-independent method, but not a processor-independent method:

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

This should work on any processor that uses the IEEE 754 floating point format (which makes x86).

UPDATE: checked and updated.

+18
Dec 17 '09 at 19:08
source share

This works for both float and double :

 double NAN = 0.0/0.0; double POS_INF = 1.0 /0.0; double NEG_INF = -1.0/0.0; 

Edit: As already mentioned, the old IEEE standard said that such values ​​should cause traps. But new compilers almost always turn off the traps and return the given values, since capture interferes with error handling.

+16
Dec 17 '09 at 19:26
source share
 double a_nan = strtod("NaN", NULL); double a_inf = strtod("Inf", NULL); 
+12
Aug 01 '14 at 1:07
source share
 <inf.h> /* IEEE positive infinity. */ #if __GNUC_PREREQ(3,3) # define INFINITY (__builtin_inff()) #else # define INFINITY HUGE_VALF #endif 

and

 <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. */ 
+3
Mar 04 '13 at 0:14
source share

I am also surprised that these are not compile-time constants. But I suppose you could easily create these values ​​by simply executing an instruction that returns such an invalid result. Division by 0, log 0, tan 90, something like.

0
Dec 17 '09 at 19:09
source share

I usually use

 #define INFINITY (1e999) 

or

 const double INFINITY = 1e999 

which works, at least in the context of IEEE 754, because the highest represented double value is approximately 1e308 . 1e309 will work as well as 1e99999 , but three nines are sufficient and memorable. Since this is either a double literal (in the case of #define ) or the actual value of Inf , it will remain infinite even if you use 128-bit ("long double") floats.

0
Jul 15 '14 at 22:58
source share



All Articles