Use isNaN when checking for NaN

When checking whether a number is NaN, use isNaN rather than == NaN.

Note that, unlike most rules here, this one is not Scala specific. NaN equality behaves unintuitively everywhere NaN exists.

Reason

By specification, NaN is not equal to anything, not even itself:

Double.NaN == Double.NaN
// res0: Boolean = false

Use isNaN instead, which is meant for just this task:

Double.NaN.isNaN
// res1: Boolean = true

Exception to the rule

There’s one scenario in which you shouldn’t use isNaN: if you’re working with a lot of numbers and need to manually validate each one of them. isNaN can be a bit slow - it’s been much improved in 2.12+, but still has a small cost.

If you identify this as a bottleneck, you always have the option of being clever. The two following methods produce the same result, but the second one is faster:

def slowFilterNaN(ds: Seq[Double]): Seq[Double] = ds.filter(d => !d.isNaN)

def fastFilterNaN(ds: Seq[Double]): Seq[Double] = ds.filter(d => d == d)

Note that this is an optimisation, and one that is sure to mystify some readers. It should only be used when a bottleneck is identified, as the runtime gain is otherwise guaranteed to be lower than the human cost of explaining it over and over again.

Checked by

LinterRule
Scala Linter
Scapegoat
  • NanComparison