Just out of curiosity.
It doesn't seem very logical that typeof NaN
is number. Just like NaN === NaN
or NaN == NaN
returning false, by the way. Is this one of the peculiarities of javascript, or would there be a reason for this?
Edit: thanks for your answers. It's not an easy thing to get ones head around though. Reading answers and the wiki I understood more, but still, a sentence like
A comparison with a NaN always returns an unordered result even when comparing with itself. The comparison predicates are either signaling or non-signaling, the signaling versions signal an invalid exception for such comparisons. The equality and inequality predicates are non-signaling so x = x returning false can be used to test if x is a quiet NaN.
just keeps my head spinning. If someone can translate this in human (as opposed to, say, mathematician) readable language, I would be gratefull.
Javascript uses NaN to represent anything it encounters that can't be represented any other way by its specifications. It does not mean it is not a number. It's just the easiest way to describe the encounter. NaN means that it or an object that refers to it could not be represented in any other way by javascript. For all practical purposes, it is 'unknown'. Being 'unknown' it cannot tell you what it is nor even if it is itself. It is not even the object it is assigned to. It can only tell you what it is not, and not-ness or nothingness can only be described mathematically in a programming language. Since mathematics is about numbers, javascript represents nothingness as NaN. That doesn't mean it's not a number. It means we can't read it any other way that makes sense. That's why it can't even equal itself. Because it doesn't.
NaN != NaN
because they are not necessary the SAME non-number. Thus it makes a lot of sense... Also why floats have both +0.00 and -0.00 that are not the same. Rounding may do that they are actually not zero.As for typeof, that depends on the language. And most languages will say that NaN is a float, double or number depending on how they classify it... I know of no languages that will say this is an unknown type or null.
A better name for
NaN
, describing its meaning more precisely and less confusingly, would be a numerical exception. It is really another kind of exception object disguised as having primitive type (by the language design), where at the same it is not treated as primitive in its false self-comparison. Whence the confusion. And as long as the language "will not make its mind" to choose between proper exception object and primitive numeral, the confusion will stay.The infamous non-equality of
NaN
to itself, both==
and===
is a manifestation of the confusing design forcing this exception object into being a primitive type. This breaks the fundamental principle that a primitive is uniquely determined by its value. IfNaN
is preferred to be seen as exception (of which there can be different kinds), then it should not be "sold" as primitive. And if it is wanted to be primitive, that principle must hold. As long as it is broken, as we have in JavaScript, and we can't really decide between the two, the confusion leading to unnecessary cognitive load for everyone involved will remain. Which, however, is really easy to fix by simply making the choice between the two:NaN
a special exception object containing the useful information about how the exception arose, as opposed to throwing that information away as what is currently implemented, leading to harder-to-debug code;NaN
an entity of the primitive typenumber
(that could be less confusingly called "numeric"), in which case it should be equal to itself and cannot contain any other information; the latter is clearly an inferior choice.The only conceivable advantage of forcing
NaN
intonumber
type is being able to throw it back into any numerical expression. Which, however, makes it brittle choice, because the result of any numerical expression containingNaN
will either beNaN
, or leading to unpredictable results such asNaN < 0
evaluating tofalse
, i.e. returningboolean
instead of keeping the exception.And even if "things are the way they are", nothing prevents us from making that clear distinction for ourselves, to help make our code more predictable and easierly debuggable. In practice, that means identifying those exceptions and dealing with them as exceptions. Which, unfortunately, means more code but hopefully will be mitigated by tools such as TypeScript of Flowtype.
And then we have the messy quiet vs noisy aka signalling
NaN
distinction. Which really is about how exceptions are handled, not the exceptions themselves, and nothing different from other exceptions.Similarly,
Infinity
and+Infinity
are elements of numeric type arising in the extension of the real line but they are not real numbers. Mathematically, they can be represented by sequences of real numbers converging to either+
or-Infinity
.NaN is still a numeric type, but it represents value that could not represent a valid number.
The best way to think of NAN is that its not a known number. Thats why NAN != NAN because each NAN value represents some unique unknown number. NANs are necessary because floating point numbers have a limited range of values. In some cases rounding occurs where the lower bits are lost which leads to what appears to be nonsense like 1.0/11*11 != 1.0. Really large values which are greater are NANs with infinity being a perfect example.
Given we only have ten fingers any attempt to show values greater than 10 are impossible, which means such values must be NANs because we have lost the true value of this greater than 10 value. The same is true of floating point values, where the value exceeds the limits of what can be held in a float.
NaN
is a number from a type point of view, but is not a normal number like 1, 2 or 329131. The name "Not A Number" refers to the fact that the value represented is special and is about the IEEE format spec domain, not javascript language domain.