In some languages, NaN equals NaN (e.g. Java, Scala); in some, it doesn’t (e.g. Python); and in some, it really doesn’t (e.g. JavaScript). To be safe, if you ever need to check for NaN, use the language’s isNaN or equivalent. But out of curiosity, let’s see what happens when we compare NaN to NaN the naive way.

Java

  • An instance of NaN always .equals() NaN.
  • An instance of NaN == itself, but not any other instance.
  • Primitive NaN never == NaN because boxing primitive NaN produces a different instance every time.
  • Float NaN behaves the same as Double NaN, but they never .equals() each other (and cannot be compared with ==).

Java 10.0.1:

jshell> Double boxedNaN = Double.NaN
boxedNaN ==> NaN

jshell> Double otherBoxedNaN = Double.NaN
otherBoxedNaN ==> NaN

jshell> double primitiveNaN = Double.NaN
primitiveNaN ==> NaN

jshell> boxedNaN.equals(boxedNaN)
$4 ==> true

jshell> boxedNaN.equals(otherBoxedNaN)
$5 ==> true

jshell> boxedNaN.equals(primitiveNaN)
$6 ==> true

jshell> boxedNaN == boxedNaN
$7 ==> true

jshell> boxedNaN == otherBoxedNaN
$8 ==> false

jshell> primitiveNaN == primitiveNaN
$9 ==> false

jshell> boxedNaN.equals(Float.NaN)
$10 ==> false

Bonus: Not all mathematical operations involving NaN necessarily result in NaN:

jshell> Math.pow(Double.NaN, 0)
$1 ==> 1.0

Scala

Scala behaves the same as Java (Scala’s .equals() is Java’s .equals(), and Scala’s eq is Java’s ==), but Scala also has its own ==, and whether NaN == NaN depends on the version.

Up to and including Scala 2.12.1:

  • An instance of NaN == itself, but not any other instance.
  • Primitive NaN never == NaN.

Since Scala 2.12.2 (specifically, this commit):

  • NaN never == NaN.

Scala 2.12.6:

scala> val boxedNaN: java.lang.Double = Double.NaN
boxedNaN: Double = NaN

scala> boxedNaN.equals(boxedNaN)
res0: Boolean = true

scala> boxedNaN eq boxedNaN
res1: Boolean = true

scala> boxedNaN == boxedNaN
res2: Boolean = false

Bonus: Same as Java:

scala> math.pow(Double.NaN, 0)
res0: Double = 1.0

Python

  • NaN never == NaN.
  • An instance of NaN is itself, but not any other instance.
  • math.nan (introduced in Python 3.5) is a constant, but float('nan') produces a different instance every time.
  • NaN is truthy.

Python 3.7.0:

>>> import math
>>> math.nan == math.nan
False
>>> math.nan is math.nan
True
>>> float('nan') == float('nan')
False
>>> float('nan') is float('nan')
False
>>> bool(math.nan)
True

Bonus: Same as Java and Scala, plus an additional case:

>>> math.pow(math.nan, 0)
1.0
>>> math.pow(1, math.nan)
1.0

JavaScript

  • NaN never == NaN.
  • NaN never === NaN.
  • NaN is falsy.

Node 8.11.3:

> NaN == NaN
false
> NaN === NaN
false
> !!NaN
false

Bonus: Same as Java and Scala:

> Math.pow(NaN, 0)
1