In Java, what does NaN mean?
Asked Answered
O

11

125

I have a program that tries to shrink a double down to a desired number. The output I get is NaN.

What does NaN mean in Java?

Overrefinement answered 11/4, 2010 at 17:57 Comment(3)
There is a good description of NaN and of the common pitfalls when using NaN in Java: ppkwok.blogspot.co.uk/2012/11/…Furie
If you are asking "what good is NaN?" in Java (or any other language), I can give you a use case where it is very handy: when I have a 2-D array of floats, but my calculation has no meaningful value for some portion of that 2-D array, I'll fill that value with "NaN". This can be used to signal downstream users of my calculation (such as when it is turned into a raster image) "don't pay attention to the value at this point". Very useful!Raimund
BTW, what -- exactly -- does it mean to "shrink" a double? Curious...Raimund
W
167

Taken from this page:

"NaN" stands for "not a number". "Nan" is produced if a floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.

Waler answered 11/4, 2010 at 18:0 Comment(7)
Additionally, NaN is defined by The IEEE Standard for Floating-Point Arithmetic (IEEE 754) quite explicitly which Java follows blindly. Reading the standard opens your eyes to a lot of things, the multiple values of zero being one of the things.Ligulate
Also, NaN has the interesting property of being the only "number" which is not the same as itself when compared. Therefore a common (and in many languages the only) test if a number x is NaN is the following: boolean isNaN(x){return x != x;}Tuff
Just as an aside: JavaScript's native isNaN(...) does not work like @quazgar's function. Instead, it even returns true when passing it a non-number, like a primitive string, an object, or undefined. In those cases, x !== x yields false instead. So, quazgar's version nicely checks if x is a NaN number. (I know the question is about Java, not JavaScript.)Peen
..."Taking square root of negative number is undefined (in arithmetics)"... Its not! its actually i and some languages like python deal very well with it... It may be not the case in java thouChalcography
@RafaelT I'd say it is undefined in non-complex arithmetic. There is no way to assign a complex number to a float or double in Java. Python is dynamically typed, therefore it may be possibly to just return a complex number in this case.Phonotypy
@Phonotypy agreed, although if it's a complex number then it's definitely not not a number :)Robbie
However, if x is a proper nonzero floating point number, x / 0 is positive or negative infinity according to the sign of x.Surfboat
N
20

NaN means “Not a Number” and is basically a representation of a special floating point value in the IEE 754 floating point standard. NaN generally means that the value is something that cannot be expressed with a valid floating point number.

A conversion will result in this value, when the value being converted is something else, for example when converting a string that does not represent a number.

Nolly answered 11/4, 2010 at 18:1 Comment(1)
Converting how? With parseFloat() or parseDouble? Or something else?Surfboat
T
15

NaN means "Not a Number" and is the result of undefined operations on floating point numbers like for example dividing zero by zero. (Note that while dividing a non-zero number by zero is also usually undefined in mathematics, it does not result in NaN but in positive or negative infinity).

Turner answered 11/4, 2010 at 17:59 Comment(0)
M
12

Minimal runnable example

The first thing that you have to know, is that the concept of NaN is implemented directly on the CPU hardware.

All major modern CPUs seem to follow IEEE 754 which specifies floating point formats, and NaNs, which are just special float values, are part of that standard.

Therefore, the concept will be the very similar across any language, including Java which just emits floating point code directly to the CPU.

Before proceeding, you might want to first read up the following answers I've written:

Now for some Java action. Most of the functions of interest that are not in the core language live inside java.lang.Float.

Nan.java

import java.lang.Float;
import java.lang.Math;

public class Nan {
    public static void main(String[] args) {
        // Generate some NaNs.
        float nan            = Float.NaN;
        float zero_div_zero  = 0.0f / 0.0f;
        float sqrt_negative  = (float)Math.sqrt(-1.0);
        float log_negative   = (float)Math.log(-1.0);
        float inf_minus_inf  = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
        float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
        float quiet_nan1     = Float.intBitsToFloat(0x7fc00001);
        float quiet_nan2     = Float.intBitsToFloat(0x7fc00002);
        float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
        float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
        float nan_minus      = -nan;

        // Generate some infinities.
        float positive_inf   = Float.POSITIVE_INFINITY;
        float negative_inf   = Float.NEGATIVE_INFINITY;
        float one_div_zero   = 1.0f / 0.0f;
        float log_zero       = (float)Math.log(0.0);

        // Double check that they are actually NaNs.
        assert  Float.isNaN(nan);
        assert  Float.isNaN(zero_div_zero);
        assert  Float.isNaN(sqrt_negative);
        assert  Float.isNaN(inf_minus_inf);
        assert  Float.isNaN(inf_times_zero);
        assert  Float.isNaN(quiet_nan1);
        assert  Float.isNaN(quiet_nan2);
        assert  Float.isNaN(signaling_nan1);
        assert  Float.isNaN(signaling_nan2);
        assert  Float.isNaN(nan_minus);
        assert  Float.isNaN(log_negative);

        // Double check that they are infinities.
        assert  Float.isInfinite(positive_inf);
        assert  Float.isInfinite(negative_inf);
        assert !Float.isNaN(positive_inf);
        assert !Float.isNaN(negative_inf);
        assert one_div_zero == positive_inf;
        assert log_zero == negative_inf;
            // Double check infinities.

        // See what they look like.
        System.out.printf("nan            0x%08x %f\n", Float.floatToRawIntBits(nan           ), nan           );
        System.out.printf("zero_div_zero  0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
        System.out.printf("sqrt_negative  0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
        System.out.printf("log_negative   0x%08x %f\n", Float.floatToRawIntBits(log_negative  ), log_negative  );
        System.out.printf("inf_minus_inf  0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
        System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
        System.out.printf("quiet_nan1     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1    ), quiet_nan1    );
        System.out.printf("quiet_nan2     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2    ), quiet_nan2    );
        System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
        System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
        System.out.printf("nan_minus      0x%08x %f\n", Float.floatToRawIntBits(nan_minus     ), nan_minus     );
        System.out.printf("positive_inf   0x%08x %f\n", Float.floatToRawIntBits(positive_inf  ), positive_inf  );
        System.out.printf("negative_inf   0x%08x %f\n", Float.floatToRawIntBits(negative_inf  ), negative_inf  );
        System.out.printf("one_div_zero   0x%08x %f\n", Float.floatToRawIntBits(one_div_zero  ), one_div_zero  );
        System.out.printf("log_zero       0x%08x %f\n", Float.floatToRawIntBits(log_zero      ), log_zero      );

        // NaN comparisons always fail.
        // Therefore, all tests that we will do afterwards will be just isNaN.
        assert !(1.0f < nan);
        assert !(1.0f == nan);
        assert !(1.0f > nan);
        assert !(nan == nan);

        // NaN propagate through most operations.
        assert Float.isNaN(nan + 1.0f);
        assert Float.isNaN(1.0f + nan);
        assert Float.isNaN(nan + nan);
        assert Float.isNaN(nan / 1.0f);
        assert Float.isNaN(1.0f / nan);
        assert Float.isNaN((float)Math.sqrt((double)nan));
    }
}

GitHub upstream.

Run with:

javac Nan.java && java -ea Nan

Output:

nan            0x7fc00000 NaN
zero_div_zero  0x7fc00000 NaN
sqrt_negative  0xffc00000 NaN
log_negative   0xffc00000 NaN
inf_minus_inf  0x7fc00000 NaN
inf_times_zero 0x7fc00000 NaN
quiet_nan1     0x7fc00001 NaN
quiet_nan2     0x7fc00002 NaN
signaling_nan1 0x7fa00001 NaN
signaling_nan2 0x7fa00002 NaN
nan_minus      0xffc00000 NaN
positive_inf   0x7f800000 Infinity
negative_inf   0xff800000 -Infinity
one_div_zero   0x7f800000 Infinity
log_zero       0xff800000 -Infinity

So from this we learn a few things:

  • weird floating operations that don't have any sensible result give NaN:

    • 0.0f / 0.0f
    • sqrt(-1.0f)
    • log(-1.0f)

    generate a NaN.

    In C, it is actually possible to request signals to be raised on such operations with feenableexcept to detect them, but I don't think it is exposed in Java: Why does integer division by zero 1/0 give error but floating point 1/0.0 returns "Inf"?

  • weird operations that are on the limit of either plus or minus infinity however do give +- infinity instead of NaN

    • 1.0f / 0.0f
    • log(0.0f)

    0.0 almost falls in this category, but likely the problem is that it could either go to plus or minus infinity, so it was left as NaN.

  • if NaN is the input of a floating operation, the output also tends to be NaN

  • there are several possible values for NaN 0x7fc00000, 0x7fc00001, 0x7fc00002, although x86_64 seems to generate only 0x7fc00000.

  • NaN and infinity have similar binary representation.

    Let's break down a few of them:

    nan          = 0x7fc00000 = 0 11111111 10000000000000000000000
    positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
    negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
                                | |        |
                                | |        mantissa
                                | exponent
                                |
                                sign
    

    From this we confirm what IEEE754 specifies:

    • both NaN and infinities have exponent == 255 (all ones)
    • infinities have mantissa == 0. There are therefore only two possible infinities: + and -, differentiated by the sign bit
    • NaN has mantissa != 0. There are therefore several possibilities, except for mantissa == 0 which is infinity
  • NaNs can be either positive or negative (top bit), although it this has no effect on normal operations

Tested in Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.

Melone answered 14/4, 2019 at 8:7 Comment(1)
Worth noting that Double also has these methods and fields (isNan, POSITIVE_INFINITY etc.) - but Integer and Long don't.Strangles
M
5

NaN means "Not a number." It's a special floating point value that means that the result of an operation was not defined or not representable as a real number.

See here for more explanation of this value.

Mangan answered 11/4, 2010 at 17:59 Comment(0)
E
5

NaN stands for Not a Number. It is used to signify any value that is mathematically undefined. Like dividing 0.0 by 0.0. You can look here for more information: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm

Post your program here if you need more help.

Episcopate answered 11/4, 2010 at 18:1 Comment(0)
P
4

NaN = Not a Number.

Parkerparkhurst answered 11/4, 2010 at 17:59 Comment(0)
P
4

Means Not a Number. It is a common representation for an impossible numeric value in many programming languages.

Parquetry answered 11/4, 2010 at 18:4 Comment(0)
P
3

Not a Java guy, but in JS and other languages I use it's "Not a Number", meaning some operation caused it to become not a valid number.

Phylactery answered 11/4, 2010 at 17:59 Comment(0)
I
3

It literally means "Not a Number." I suspect something is wrong with your conversion process.

Check out the Not A Number section at this reference

Inkle answered 11/4, 2010 at 17:59 Comment(0)
L
3

Not a valid floating-point value (e.g. the result of division by zero)

http://en.wikipedia.org/wiki/NaN

Langley answered 11/4, 2010 at 17:59 Comment(2)
I quibble with this answer. First: "NaN" IS a valid value for an IEEE float! (After all, it is defined in the spec... so its "valid", right?). Second: "division by zero" can be represented by IEEE "Positive Infinity" or "Negative Infinity"; a better example of "NaN" is "zero divided by zero", as some other answers have correctly pointed out.Raimund
"Valid value" and "defined in spec" is not the same thing. Agreed to 0/0.Langley

© 2022 - 2024 — McMap. All rights reserved.