What is NaN in Java, and why does NaN == NaN evaluate to false? How do you correctly test whether a value is NaN?
answer
- NaN = Not a Number, from 0.0/0.0 or sqrt(-1)
- All comparisons with NaN are false; only != is true
- x != x is true only for NaN
- Use Double.isNaN / Float.isNaN to detect
- Wrapper equals/compare treat NaN as equal & largest (opposite of ==)
basics
~10 sNaN means 'Not a Number' and comes from undefined operations like 0.0/0.0. It is never equal to anything, even itself, so NaN == NaN is false. Use Double.isNaN(x) to check for it.
solid answer
~40 sNaN (Not a Number) is a special double/float value produced by mathematically undefined operations such as 0.0/0.0, Math.sqrt(-1), or Infinity - Infinity. The IEEE 754 standard requires every ordered comparison with NaN to return false, and equality (==) to return false too — including NaN == NaN. The != operator is the only one that returns true for NaN. Because of this, you cannot detect NaN with ==; the correct check is Double.isNaN(x) (or Float.isNaN). A side effect is that any collection sort, min/max, or 'x is in range' check involving NaN can silently misbehave. Note that Double.equals and the wrapper's compareTo treat NaN as equal-to-itself and greater-than-everything, which is the opposite of the primitive == behavior.
code
java · 9 linesdouble n = 0.0 / 0.0; // NaN
System.out.println(n == n); // false (!)
System.out.println(n != n); // true
System.out.println(Double.isNaN(n)); // true — the correct check
// Wrapper / total-ordering path disagrees on purpose:
System.out.println(Double.valueOf(n).equals(Double.NaN)); // true
System.out.println(Double.compare(n, n)); // 0 (equal)
System.out.println(Double.compare(n, 1.0)); // > 0 (NaN is largest)go deeper
Knows NaN comes from undefined operations and that you must use Double.isNaN, not ==.
Explains the IEEE 754 'unordered' rule: all comparisons false, != true, and why == can't detect NaN.
Distinguishes primitive == behavior from Double.equals/compare total ordering and the practical impact on sorting, ranges, and validation.
Can reason about NaN as a poison/propagation value in numerical pipelines, design defensive APIs that validate inputs, and explain the equals/compareTo contract tradeoff.
## What floating-point numbers are Java's `double` (64-bit) and `float` (32-bit) store real numbers using the **IEEE 754** standard. A floating-point value is split into a sign bit, an exponent, and a mantissa (fraction). Most bit patterns represent ordinary numbers, but a few patterns are reserved for *special values*: positive/negative infinity and **NaN** (Not a Number). ## What NaN is **NaN** stands for *Not a Number*. It is the result the hardware produces when an operation has **no meaningful real-number answer**. Examples in Java: - `0.0 / 0.0` → NaN (zero divided by zero is undefined) - `Math.sqrt(-1.0)` → NaN (no real square root of a negative) - `Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY` → NaN - `0.0 * Double.POSITIVE_INFINITY` → NaN - `Math.log(-1.0)` → NaN Important: integer `0/0` does **not** produce NaN — it throws `ArithmeticException`. NaN exists only for `float`/`double`. ## Why NaN == NaN is false IEEE 754 defines NaN as **unordered**: it has no position on the number line, so it cannot be 'less than', 'equal to', or 'greater than' any value — including another NaN. The standard therefore mandates that **every ordered comparison involving NaN returns `false`**, and equality returns `false` too. The one exception is `!=`, which returns `true` (since 'not equal' is the logical negation). So: ``` NaN == NaN -> false NaN != NaN -> true // the classic idiom for 'is it NaN?' NaN < 5 -> false NaN >= 5 -> false ``` This is intentional: it lets `NaN` propagate through a computation as a poison value rather than silently looking like a normal number. ## How to correctly detect NaN Because `==` always fails on NaN, use the library helper: ```java Double.isNaN(x); // for double Float.isNaN(f); // for float ``` The old idiom `x != x` also works (it is `true` only for NaN) but is unclear; prefer `isNaN`. ## The wrapper-class twist The **primitive** `==` and the **object** comparisons disagree on purpose: - `new Double(Double.NaN).equals(Double.NaN)` → **true** - `Double.compare(Double.NaN, Double.NaN)` → **0** (equal) - `Double.compare(Double.NaN, 1.0)` → **positive** (NaN sorts as the largest value) This 'total ordering' is deliberate so that `HashMap` keys, `TreeSet`, and `Arrays.sort` behave consistently (a sort needs a consistent ordering; raw NaN comparisons would break it). So the rule to remember: **primitive comparisons treat NaN as unequal-to-everything; the boxed/`compare` paths treat NaN as equal-to-itself and largest.** ## Practical consequences - A `for` loop guarded by `x < limit` will exit immediately if `x` is NaN. - `Math.max`/`Math.min` return NaN if either argument is NaN (they propagate it). - Filtering or validating user-supplied doubles should include an explicit `isNaN` check.
- Why do Double.equals and Double.compare treat NaN as equal to itself when == does not?To give a consistent total ordering so collections (TreeSet, sort, HashMap keys) and Comparable contracts work; raw NaN's unordered semantics would violate the equals/compareTo contract and break sorting.
- What does Math.max(Double.NaN, 5.0) return?NaN — Math.max and Math.min propagate NaN rather than ignoring it.
saying these in an interview costs you the question
- Thinking you can check NaN with x == Double.NaN (always false)
- Believing integer 0/0 gives NaN (it throws ArithmeticException)
- Assuming Double.equals matches primitive == for NaN (it doesn't)
- Forgetting NaN poisons sorts, min/max, and range checks