32
float f = (float)'a';
if(f < 0){ 
}   
else if(f == 0){ 
}   
else if(f > 0){ 
}   
else{
    printf("NaN\n");                                                          
}   

f won't be greater/equal/less than 0 if it's a NaN.

But how to produce such a f in the first place?

I tried various ways to produce a NaN,but none work..

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Je Rog
  • 5,675
  • 8
  • 39
  • 47
  • 1
    http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html – Matt Ball Aug 27 '11 at 03:31
  • 1
    Can you use a little C++? C++ has the std::numeric_limits stuff which includes constants for both quiet and signalling NaN. Also, are you sure your system supports NaN correctly? Because I'm REALLY surprised when you say that 0.0/0.0 isn't NaN, and I start to suspect your library isn't setup the way you think it is. – Michael Kohne Aug 27 '11 at 03:34
  • Here I show how various NaNs look like when generated by different means: https://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan/55648118#55648118 C++ version: https://stackoverflow.com/questions/16691207/c-c-nan-constant-literal – Ciro Santilli OurBigBook.com Apr 12 '19 at 09:48

9 Answers9

27

Using floating point numbers, 0.0 / 0.0 isn't a "divide by zero" error; it results in NaN.

This C program prints -nan:

#include <stdio.h>

int main()
{
    float x = 0.0 / 0.0;
    printf("%f\n", x);
    return 0;
}

In terms what NaN looks like to the computer, two "invalid" numbers are reserved for "signaling" and "quiet" NaN (similar to the two invalid numbers reserved for positive and negative infinity). The Wikipedia entry has more details about how NaN is represented as an IEE floating point number.

Dan Cecile
  • 2,403
  • 19
  • 21
  • @Je Rog: My bad, I've fixed my answer. – Dan Cecile Aug 27 '11 at 03:29
  • @William ,it works! But how's `NaN` represented under the hood? It means that IEEE standard formats for single and double-precision values defines some invalid value,which may be used as `NaN`,right? – Je Rog Aug 27 '11 at 03:30
  • 1
    @Matt Ball,does it mean IEEE contains definition for **less than** 2^128 float point values? Only in that case there can be some special values used as NaN IMO – Je Rog Aug 27 '11 at 03:38
  • Why `0/0` produces Floating point exception,while 0.0/0.0 produces NaN ,confused a lot! – Je Rog Aug 27 '11 at 03:45
  • @Je Rog: `0/0` isn't a floating point exception, it's an integer exception. Integers can't represent NaN or infinity, so `0/0` and `1/0` will crash your program instead of producing garbage values. – Dan Cecile Aug 27 '11 at 03:48
  • @Je Rog 0/0 is an integer division, causing an exception. 0.0/0.0 is a floating point division, for which the result is a NaN – Foo Bah Aug 27 '11 at 03:48
  • `gcc (GCC) 4.1.2 20080704` will report `0/0` as `Floating point exception` at least. – Je Rog Aug 27 '11 at 03:56
  • @Je Rog: OK, I see. It's a problem with integers though, because the zeros in `0/0` don't have any decimal points. When C sees a number like `0` or `231`, it treats it like an integer. Numbers like `0.0`, `1.392f`, and `332.4` are treated as floating point numbers. – Dan Cecile Aug 27 '11 at 04:03
  • 2
    @Dan Cecile: I think division by zero will produce an Indeterminate (IND) number, not NaN. – MNS Oct 06 '14 at 10:01
  • 2
    @MNS integer division by zero is undefined behavior. There is no “indeterminate number” or “IND” in C. – Pascal Cuoq Feb 11 '16 at 10:22
  • @PascalCuoq I was referring float division by zero as shown in the answer above. Microsoft C 2012 complier produces IND number in this case. But as you rightly said integer division by zero is undefined or will throw exception. – MNS Feb 12 '16 at 05:23
  • Visual Studio (I'm using 2015) still detects this as a compile time failure, C2124, so this is not portable. – Kit10 Mar 01 '17 at 20:39
  • 1
    @Copperpot Yes, the issue with Microsoft compilers is well-known. See [my answer](http://stackoverflow.com/a/43496916/3782797) (I've just posted) for a solution with these compilers (used by GNU MPFR) and other solutions for various implementations, each time mentioning portability issues. – vinc17 Apr 19 '17 at 13:26
26

To produce a nan, there are a few ways:

1) generate it manually (read ieee754 to set up the bits properly)

2) use a macro. GCC exposes a macro NAN. It's defined in math.h

The general way to check for a nan is to check if (f == f) (which should fail for nan values)

For nan, the exponent bits in the float representation should all be set to 1 (float consists of a signed bit, a set of exponent bits and a set of mantissa bits)

Foo Bah
  • 25,660
  • 5
  • 55
  • 79
  • 5
    You can also use `isnan()` to check for a NaN (requires C99 or (on unix systems) appropriate feature flags, see the manpage for details) – bdonlan Aug 27 '11 at 03:36
  • 1
    @bdonlan slightly OT but its actually strange that python didn't introduce isnan until 2.6 – Foo Bah Aug 27 '11 at 03:49
  • I find NAN in bits/nan.h for my toolset. – DarenW Sep 25 '15 at 20:34
  • For (1), there are various portability issues not covered by IEEE 754 (see [my answer](http://stackoverflow.com/a/43496916/3782797) for some details). About (2), the `NAN` does not come from GCC, but from the C library. For instance, see the `.../bits/nan.h` file for the GNU libc (as mentioned by @DarenW); however, the macro definition is specific to GCC when detected via preprocessor tests. – vinc17 Apr 19 '17 at 13:37
  • "For nan, the exponent bits in the float representation should all be set to 1" - That is true for both `nan` and `inf`. – Matt Mar 01 '19 at 17:15
14

You can either use NAN macro, or simply one of nan/nanf functions to assign a nan value to a variable.
to check if you are dealing with a nan value, you can use isnan(). Here is an example:

#include <stdio.h>
#include <math.h>

int main(void) {

    float a = NAN;//using the macro in math.h
    float f = nanf("");//using the function version 
    double d = nan("");//same as above but for doubles!

    printf("a = %f\nf = %f\nd = %f\n",a,f,d);

    if(isnan(a))
        puts("a is a not a number!(NAN)\n");

    return 0;
}

Running the code snippet above will give you this output:

a = nan
f = nan
d = nan
a is a not a number!(NAN)

Run the code yourself : http://ideone.com/WWZBl8
read more information : http://www.cplusplus.com/reference/cmath/NAN/

Hossein
  • 24,202
  • 35
  • 119
  • 224
3

For hosted C implementations, one can do a #include <math.h> and use the NAN macro if defined. For instance, with GCC, it is implemented by a builtin: (__builtin_nanf ("")).

For freestanding C implementations (on which the <math.h> header may not be available) or when the NAN macro is not defined (which might happen even though NaN's may be supported), one can generate a NaN with a floating-point operation such as 0.0 / 0.0. However, there may be several issues with it.

First, such an operation also generates an exception, with a possible trap on some C implementations. One can make sure that it is computed at compile time with:

static double my_nan = 0.0 / 0.0;

Another issue is that Microsoft Visual C++ (at least some versions) attempts to evaluate 0.0 / 0.0 at compile time (even when this expression is in an arbitrary place in the code) and complains about its validity. So, the solution here is the opposite one: make sure that the compiler will not evaluate it at compile time, by doing:

static double zero = 0.0;

and then use zero / zero. Since these solutions are conflicting, one can test the compiler with preprocessor directives (#if...) on specific macros.

One may also choose a solution based on the NaN encoding, but there are also portability issues. First, the IEEE 754 standard does not completely define the encoding of a NaN, in particular the way to distinguish quiet and signaling NaNs (and hardware differs in practice); signaling NaNs will yield undefined behavior. Moreover, the IEEE 754 standard does not define how the bit string is represented in memory, i.e. the endianness may need to be detected. If these problems are solved, a union or an array of unsigned char with a pointer cast is fine to get the floating-point type. Do not use an integer with a pointer cast on its address to do type punning as this will break the C aliasing rules.

vinc17
  • 2,829
  • 17
  • 23
3

From the GNU GCC manual math.h defines macros that allow you to explicitly set a variable to infinity or NaN. Since this is a part of C99 you can use the following macros with other c99 compliant compilers i hope.

— Macro: float INFINITY An expression representing positive infinity. It is equal to the value produced by mathematical operations like 1.0 / 0.0. -INFINITY represents negative infinity.

You can test whether a floating-point value is infinite by comparing it to this macro. However, this is not recommended; you should use the isfinite macro instead. See Floating Point Classes.

This macro was introduced in the ISO C99 standard.

— Macro: float NAN An expression representing a value which is “not a number”. This macro is a GNU extension, available only on machines that support the “not a number” value—that is to say, on all machines that support IEEE floating point.

You can use ‘#ifdef NAN’ to test whether the machine supports NaN. (Of course, you must arrange for GNU extensions to be visible, such as by defining _GNU_SOURCE, and then you must include math.h.)

for further information you can see here: http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

A. K.
  • 34,395
  • 15
  • 52
  • 89
  • The `NAN` macro is not a GNU extension (well, at least not any longer). It has been introduced in the ISO C99 standard. So, instead of defining `_GNU_SOURCE`, compiling in some form of C99 mode or higher (instead of C89) is sufficient. – vinc17 Apr 19 '17 at 13:50
2

A -nan can also be produced by setting all 32 bits of a float variable as 1, as shown below:

float nan_val = 0xffffffff;

Also, you can compare if a float variable is -nan explicitly by checking if comparison with itself fails.

if (nan_val != nan_val) {
// executes iff nan_val is -nan
}

This method of comparison should work for compilers that use IEEE floats.

tonyjosi
  • 717
  • 1
  • 9
  • 17
0

This works for constants too (0/0 will give a compiler error on vs):

const unsigned maxU = ~0;
const float qNan =  *((float*)&maxU);
Oliver Zendel
  • 2,695
  • 34
  • 29
  • 1
    There are at least 4 portability issues: `~` on a signed integer type, `int` potentially too short (e.g. on some embedded systems), NaN representation, and broken aliasing rules. See [my answer](http://stackoverflow.com/a/43496916/3782797) for some details. – vinc17 Apr 19 '17 at 14:10
0

Following C program will produce a NaN. The second statement will result in a NaN.

#include <stdio.h>
#include <tchar.h>
#include "math.h"

int _tmain(int argc, _TCHAR* argv[])
{
    double dSQRTValue = sqrt( -1.00 ); 
    double dResult = -dSQRTValue;  // This statement will result in a NaN.
    printf( "\n %lf", dResult );

    return 0;
}

Following will be the output of the program.

1.#QNAN0

MNS
  • 1,354
  • 15
  • 26
  • >sqrt( -1.00 ); This faults on some machines. – rsaxvc May 31 '23 at 21:51
  • @rsaxvc The C standard library's sqrt() function is specified to return a NaN when given a negative argument. This behavior is consistent with the IEEE 754 floating-point standard, which is widely supported by modern processors. On the other hand, non-standard floating-point implementations may handle this case differently and may generate a fault when the input is a negative number. – MNS Jun 06 '23 at 21:20
  • you're right! My IEEE-compliant platform wasn't C-compliant. – rsaxvc Jun 07 '23 at 22:38
-3

nan is produced when we program contain value like 0.0/0.0 as said by @Dan Cecile OR sqrt(-1).