In last week’s post I looked at the differences between integral and floating point division by zero. This was caused by the difference in their binary representation in memory, as well as the difference in the rules that govern integral and floating point arithmetic.
In this post, I want to look at another interesting peculiarity, that of “NaN” (Not a Number).
Numerators and Denominators
Let’s first revise the terms “numerator” and “denominator”.
When we were first taught fractions at school, there were always two numbers involved. There was a top number and a bottom number separated by a horizontal line. The top number is called the numerator and the bottom number is the denominator.
A fraction is the numerator being divided by the denominator. The numerator represents the number of parts taken from the total parts, while the denominator represents the total parts as a whole.
Now I’m not planning to teach you how to do fractional arithmetic. You learnt that at school. I’m just going to revise a few interesting edge cases.
We were taught that:
- When the numerator has the same value as the denominator (i.e. x/x), the result was 1.
- When the numerator was zero (i.e. 0/x), the result was zero.
- When the denominator was zero (i.e. x/0), the result was infinity.
Compile and run the following code to test this.
public class Example {
public static void main (String args[]) {
double value = 42.0;
System.out.println(" value/value = " + value/value);
System.out.println(" 0.0/value = " + 0.0/value);
System.out.println(" value/0.0 = " + value/0.0);
System.out.println("-value/0.0 = " + -value/0.0);
}
} // end of class
The output is:
value/value = 1.0
0.0/value = 0.0
value/0.0 = Infinity
-value/0.0 = -Infinity
This is exactly what we expected based on the rules we were taught at school. Cool!
Indeterminate Forms
But what happens when x has the value of zero? Then all three results must be true at the same time! Obviously there is no number that can have the value of 0, 1 and infinity all at the same time. This number has been defined as “NaN”, i.e. Not a Number. It represents a undefined or unrepresentable number. This is called indeterminate form.
In mathematics, there are a few values represented by NaN. Zero divided by zero is one. The square root of a negative number is another. NaNs can also be used to represent missing values in computations.
The use of NaNs in computing was introduced by the IEEE 754 floating-point standard in 1985. This standard also included representations of positive and negative infinity.
Let’s change the value of the value
variable to zero in the previous code:
public class Example {
public static void main (String args[]) {
double value = 0.0;
System.out.println(" value/value = " + value/value);
System.out.println(" 0.0/value = " + 0.0/value);
System.out.println(" value/0.0 = " + value/0.0);
System.out.println("-value/0.0 = " + -value/0.0);
System.out.println("NaN == NaN = " + (Double.NaN==Double.NaN));
}
} // end of class
The output is now:
value/value = NaN
0.0/value = NaN
value/0.0 = NaN
-value/0.0 = NaN
NaN == NaN = false
Again, the results are as expected. Though it’s a bit unexpected that NaN is not equal to NaN. If we think about it a bit more, it becomes obvious. Interestingly, if we print Double.POSITIVE_INFINITY==Double.POSITIVE_INFINITY
, the result is true
.
There are a number of indeterminate forms involving 0, 1 and infinity:
- (±0)/(±0)
- infinity/infinity i.e. (±∞)/(±∞)
- 0 * infinity i.e. (±0) × (±∞)
- infinity – infinity
- 0 to the power of 0
- 1 to the power of infinity
- infinity to the power of zero
- Modulus x % y when x is an infinity or y is zero.
You can easily test these indeterminate forms by adding a few lines to the previous example code.
Java Support
From the previous examples, we can see that Java supports NaN as well as positive and negative infinity.
Both the Double
and the Float
wrapper classes contain the static class constants NaN
, POSITIVE_INFINITY
and NEGATIVE_INFINITY
. They also contain isFinite()
, isInfinite()
and isNaN()
methods.
If we want to print the infinity symbol we can use the Unicode escape character \u221E
as follows:
System.out.println("Infinity symbol = \u221E");
Ending Off
If you’re interested in more details, there are technical articles on Wikipedia on Nan and Indeterminate form.
These simple examples stress the importance of knowing the Java language rules well, and understanding IEEE 754 floating point maths (at least on an introductory level).
Share your comments and Java experiences. And if you enjoyed this, please share it on social media too.