1. Overview
Simply put, NaN is a numeric data type value which stands for “not a number”.
In this quick tutorial, we’ll explain the NaN value in Java and the various operations that can produce or involve this value.
2. What Is NaN?
NaN usually indicates the result of invalid operations. For example, attempting to divide zero by zero is one such operation.
We also use NaN for unrepresentable values. The square root of -1 is one such case, as we can describe the value (i) only in complex numbers.
The IEEE Standard for Floating-Point Arithmetic (IEEE 754) defines the NaN value. In Java, the floating-point types float and double implement this standard.
Java defines NaN constants of both float and double types as Float.NaN and Double.NaN:
“A constant holding a Not-a-Number (NaN) value of type double. It is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L).”
and:
“A constant holding a Not-a-Number (NaN) value of type float. It is equivalent to the value returned by Float.intBitsToFloat(0x7fc00000).”
We don’t have this type of constants for other numeric data types in Java.
3. Comparisons with NaN
While writing methods in Java, we should check that the input is valid and within the expected range. NaN value is not a valid input in most cases. Therefore, we should verify that the input value is not a NaN value and handle these input values appropriately.
NaN cannot be compared with any floating type value. This means that we’ll get false for all comparison operations involving NaN (except “!=” for which we get true).
We get true for “x != x” if and only if x is NaN:
System.out.println("NaN == 1 = " + (NAN == 1));
System.out.println("NaN > 1 = " + (NAN > 1));
System.out.println("NaN < 1 = " + (NAN < 1));
System.out.println("NaN != 1 = " + (NAN != 1));
System.out.println("NaN == NaN = " + (NAN == NAN));
System.out.println("NaN > NaN = " + (NAN > NAN));
System.out.println("NaN < NaN = " + (NAN < NAN));
System.out.println("NaN != NaN = " + (NAN != NAN));
Let’s have a look at the result of running the code above:
NaN == 1 = false
NaN > 1 = false
NaN < 1 = false
NaN != 1 = true
NaN == NaN = false
NaN > NaN = false
NaN < NaN = false
NaN != NaN = true
Hence, we cannot check for NaN by comparing with NaN using “==” or “!= “. In fact, we should rarely use “==” or “!= ” operators with float or double types.
Instead, we can use the expression “x != x”. This expression returns true only for NAN.
We can also use the methods Float.isNaN and Double.isNaN to check for these values*.* This is the preferred approach as it’s more readable and understandable:
double x = 1;
System.out.println(x + " is NaN = " + (x != x));
System.out.println(x + " is NaN = " + (Double.isNaN(x)));
x = Double.NaN;
System.out.println(x + " is NaN = " + (x != x));
System.out.println(x + " is NaN = " + (Double.isNaN(x)));
We’ll get the following result when running this code:
1.0 is NaN = false
1.0 is NaN = false
NaN is NaN = true
NaN is NaN = true
4. Operations Producing NaN
While doing operations involving float and double types, we need to be aware of the NaN values.
Some floating-point methods and operations produce NaN values instead of throwing an Exception. We may need to handle such results explicitly.
A common case resulting in not-a-number values are mathematically undefined numerical operations:
double ZERO = 0;
System.out.println("ZERO / ZERO = " + (ZERO / ZERO));
System.out.println("INFINITY - INFINITY = " +
(Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY));
System.out.println("INFINITY * ZERO = " + (Double.POSITIVE_INFINITY * ZERO));
These examples result in the following output:
ZERO / ZERO = NaN
INFINITY - INFINITY = NaN
INFINITY * ZERO = NaN
Numerical operations which don’t have results in real numbers also produce NaN:
System.out.println("SQUARE ROOT OF -1 = " + Math.sqrt(-1));
System.out.println("LOG OF -1 = " + Math.log(-1));
These statements will result in:
SQUARE ROOT OF -1 = NaN
LOG OF -1 = NaN
All numeric operations with NaN as an operand produce NaN as a result:
System.out.println("2 + NaN = " + (2 + Double.NaN));
System.out.println("2 - NaN = " + (2 - Double.NaN));
System.out.println("2 * NaN = " + (2 * Double.NaN));
System.out.println("2 / NaN = " + (2 / Double.NaN));
And the result of the above is:
2 + NaN = NaN
2 - NaN = NaN
2 * NaN = NaN
2 / NaN = NaN
Finally, we cannot assign null to double or float type variables. Instead, we may explicitly assign NaN to such variables to indicate missing or unknown values:
double maxValue = Double.NaN;
5. Conclusion
In this article, we discussed NaN and the various operations involving it. We also discussed the need to handle NaN while doing floating-point computations in Java explicitly.
The full source code can be found over on GitHub.