What is the type of NaN?

javascript numbers

Image credit: jooinn.com

I was recently answering an interesting question on Stack Overflow about the type of NaN. And indeed if you type in your browser console typeof NaN === 'number' you'll get true. The comments to the answer made me realise that this is not another one of JavaScript quirks, but in fact a standard feature of all the programming languages that implement The IEEE Standard for Floating-Point Arithmetic (IEEE 754).

In Ruby, for example NaN can be either an instance of Float or BigDecimal.

And indeed, if we look at the ECMA-262, 10th edition, the ECMAScript Language Specification, section 4.3.21 states that number type represents a "set of all possible Number values including the special “Not-a-Number” (NaN) value, positive infinity, and negative infinity". A few subsections below, section 4.3.24 clarifies that NaN is a "number value that is an IEEE 754-2008 “Not-a-Number” value".

So what is this IEEE 754 standard?

First published in 1985, its main purpose is to provide a computational method with floating point numbers, which would have the same results independent of the environment where the processing is done, be it software, hardware or a mix of both. Together with specifying formats and methods for floating-point arithmetic in computer programming environments, IEEE 754 also defines a set of special values: 0 (-0 and +0 are distinct values, although they both are equal; here's an in-depth article about both zero values in JS), denormalised number, positive and negative Infinity, and NaN, which the standard describes as a numeric data type that cannot be represented within the computing system. In fact, IEEE 754 defines two types of NaN - a quiet NaN (qNaN) and a signalling NaN (sNaN). The most important difference between the two is that sNaN will cause an exception when used in arithmetic operations and qNaN won't. It seems like in JavaScript all the NaNs are quiet, at least I wasn't able to find any information to the contrary. 

Additionally, the standard defines an interesting list of special operations and their results:

number ÷ Infinity               = 0
number ÷ -Infinity              = -0

±Infinity × ±Infinity           = ±Infinity
±non zero number ÷ ±0           = ±Infinity
number × ±Infinity	            = ±Infinity
Infinity + Infinity             = ±Infinity
Infinity – -Infinity            = +Infinity
-Infinity – Infinity            = Infinity
-Infinity + – Infinity          = Infinity

±0 ÷ ±0	                        = NaN
±Infinity ÷ ±Infinity           = NaN
±Infinity × 0	                = NaN
NaN == NaN (also '===' in JS)	//False
Testing for NaN values

JavaScript doesn't have a single NaN value, in fact, according to ECMA-262, there are "9007199254740990 (that is, 253 - 2) distinct “Not-a-Number” values of the IEEE Standard [...] represented in ECMAScript as a single special NaN value. In some implementations, external code might be able to detect a difference between various Not-a-Number values, but such behaviour is implementation-dependent; to ECMAScript code, all NaN values are indistinguishable from each other."

Because NaN doesn't equal to itself (and in fact in some programming languages self-comparison is a widely used approach to test for NaNs), we need to use a special Number.isNaN() or isNaN() methods to detect NaNs. The difference between the two is that isNaN() returns true if the value is currently NaN or it is going to be NaN after it's coerced to numeric value and Number.isNaN() only will return true if the value is currently NaN. Generally Number.isNaN() is more accurate since it also checks if the type of value is number. MDN has a handy explanation about testing against NaN.

Having "Not a Number" value to be a type of number is quite illogical, maybe a better name would be "Not a Real Number" or something along those lines. In this case, however, it's not a strange behaviour in JavaScript, but a general programming principle. 

Got any questions/comments or other kinds of feedback about this post? Let me know on Twitter.