NaN is Not a Math
NaN is Not a Math
This is a handy little article you can give to any JavaScript pro who tries to claim that NaN
(Not a Number) is "math" or "part of the IEEE standard." I demonstrate that JavaScript's use of NaN is neither math, nor is it even following the standard, which means "NaN
is math" is no defense of JavaScript's implementation.
What is NaN
NaN
is a mechanism defined by the IEEE 754 standard for indicating and signaling Floating-Point Arithmetic exceptional conditions. From the standard it says:
1.1 Scope: This standard specifies formats and methods for floating-point arithmetic in computer systems—standard and extended functions with single, double, extended, and extendable precision—and recommends formats for data interchange. Exception conditions are defined and standard handling of these conditions is specified.
This is from the actual standard document and outlines what the standard says it applies to. The purpose of NaN
in the standard is to handle situations where some floating point arithmetic operation doesn't make sense, has a failure mode, or similar situation that "should...afford retrospective diagnostic information inherited from invalid or unavailable data and results."
In JavaScript you'll get a NaN
when you attempt something like these lines of code:
> 0 / 0
NaN
However, the problem with JavaScript's NaN
comes from the way JavaScript abuses NaN
for many things that shouldn't use it, and how there are no "signaling NaNs" or diagnostic information, so trapping the error where it matters is far too difficult. There's also the issue that NaN
is not math at all, but just part of some standard.
1. IEEE 754 is Not Math
So NaN
is "math" right? As in, established via a proof that has been peer reviewed in a journal of mathematics such that it is considered a piece of the field of mathematics? I can find the paper that establishes NaN
on the same footing as, say, Principia Mathematica or Gödel's Incompleteness Theorem? Right? That exists?
No? Well then, NaN
is not math.
The reason people use this defense against JavaScript's NaN
is they think something being "math" makes it impossible to question. "Math NaN" is an unassailable proof that once established can never be refuted, disproved, undone, countered, or hated. Worse yet, hating NaN
means you're an idiot who doesn't know math. By claiming "NaN is math" they're trying to defend JavaScript's use of NaN
as if it's on the same validity level as Gödel's Theorem, and you're an idiot for not knowing this.
This is a Fallacy of False Equivalence. NaN
is not the same as Gödel's Theorem just because they both have numbers in them. In fact, NaN
is based on a standard that is specifically designed to break real floating point arithmetic so that it can work in a discrete CPU that can't efficiently do symbolic operations. If you divide 1/3 in a computer it has to make some compromises to give you some kind of close-enough answer. But, a "close enough" answer is not what mathematics is all about. Real mathematics--the kind based on real peer reviewed proofs--is based on being as logically exact as humanly possible.
IEEE Floating Point math is not perfectly exact, and that means it's also not "math". It's a bastardization of math as a practical compromise to make 1/3 work in a computer.
The Math and Bailey
Now, when you bring up this clearly obvious point that NaN
--and IEEE Floating Point--are not math you'll get a reply that attempts to move the discussion to a more reasonable claim. They'll say, "Well it's not math per-se but it is defined in a standard that we all use so..."
This rhetorical trick is called a motte-and-bailey. A "motte-and-bailey fallacy" is where someone advances a controversial position (the bailey), and when challenged, runs to a defensible narrowing of that position (the motte). Once they defend the easily defended safe motte position they come out claiming they defended the controversial bailey position.
In this case, the controversial stance is, "JavaScript's use of NaN
is irrefutable because it is mathematically the same as Gödel's Theorem." When you challenge this position, because NaN
is not math at all, they'll retreat to a more narrow claim that it's "Part of the IEEE Floating Point standard." It's easy to defend that NaN
is in the standard and JavaScript uses NaN
. That's an uncontroversial stating of a simple fact. Once they defend that position they'll then claim that the original claim of NaN
being just as proven as Gödel's Theorem is still valid, even though all they did was make the uncontroversial claim that you can find NaN
in both IEEE 754 and JavaScript.
Yet, until someone produces a proof, published in a prestigious journal of mathematics, that establishes IEEE math as equal to Gödel's Theorem then, nope, NaN
is not math.
2. Where's the Signal?
Alright, let's say the motte-and-bailey is working. Someone is retreating to the "It's in the IEEE standard" claim as a way to defend NaN
like it's Gödel's Theorem. Well then, JavaScript doesn't even follow the IEEE 754 standard.
The IEEE 754-2008 standard requires two types of NaN
: quiet qNaN
and signaling sNaN
. A qNaN
is what you get with JavaScript where the result of the operation turns into a NaN
value and the program continues running. A signaling sNaN
is intended to be a fault that aborts the current operation, much like an exception. The standard specifies exactly when to use each, but JavaScript doesn't have an sNaN
, only the quiet ones.
That's just one example of JavaScript not following the standard, which means the defense of NaN
with the claim that it's "IEEE Standard" is invalidated as well. If the "NaN
is (IEEE) math" crowd want to defend JavaScript's NaN
with the IEEE 754 standard then JavaScript better follow the standard exactly or else it's no defense at all.
It's Standard or It's Not
Standards are documents created by companies to help integrate and sell their products. These standards are not sources of truth or forces of nature that can't be questioned. You can totally question standards, but more importantly, because these documents are not universal truths they should be applied sparingly. If you take the IEEE 754 standard and attempt to apply it to things not covered in the document then you're stepping outside of the standard and it once again cannot be used as a defense.
JavaScript tosses NaN
around like it's (not a) candy. All kinds of operations not covered in the IEEE 754 standard return NaN
. Parsing integers isn't in the standard, and yet:
> parseInt("what")
NaN
This is parsing an integer, not a floating point number. Parsing is not in IEEE 754, and parsing an INTEGER is not in the standard, so JavaScript should not return a NaN
. You can't claim JavaScript's abuse of NaN
is defensible with "it's IEEE standard" when JavaScript returns NaN
from operations not...in the standard.
3. Where's the Diagnostics?
The standard mentions that a NaN
should include diagnostic information that lets someone figure out what went wrong:
Quiet NaNs should, by means left to the implementer’s discretion, afford retrospective diagnostic information inherited from invalid or unavailable data and results. To facilitate propagation of diagnostic information contained in NaNs, as much of that information as possible should be preserved in NaN results of operations.
What do you get from a JavaScript NaN
? Not much. You can test for it with isNaN
, but you can't get useful information like, where it happened, what the operands were used, or anything else. You just get a random NaN
somewhere and have to root out where it went.
For JavaScript's NaN
to be conforming (and useful) it should include the source location where it was created, as well as information on the two operands. This could be defended by referring to the "by means left to the implementer's discretion", but this doesn't say "at the implementer's discretion". It says, "by means left to", which means diagnostic information is required, but the standard won't say how it should done.
Not only would source location and operand information make NaN
conform to the standard, but it's a change that JavaScript could make now that would vastly improve NaN
as well as be backward compatible with existing code. We could have additional functions on Number
that throw exceptions, get diagnostic information, etc.
So What?
Finally, people have problems with NaN
, and trying discredit their confusion and frustration by proclaiming "it's math bro" is wrong. If I haven't convinced you that JavaScript's use of NaN
is not math, and not IEEE 754 compliant, then at a minimum you should realize that the way JavaScript
handles NaN
causes people problems, so the reply should at least be more sympathetic and educational than, "LOL learn math dood."
That's probably the biggest reason I wrote this essay. The claim that "NaN is math" is a classist insult that tries to shame people for not being good at math, when it's JavaScript's fault for not providing enough diagnostic information to make NaN
useful...as required by the standard.
More from Learn Code the Hard Way
C++ Is An Absolute Blast
Where I try to explain why I feel like C\+\+ is so much fun, and to correct some misinformation.
Just Use MSYS2 You Say?
Debunking idiots on HackerNews who think a total beginner can just 'Use MSYS2' on Windows.
Solving the Worst Problem in Programming Education: Windows
I've created a set of install scripts for Windows that helps people install many different programming languages using standard tools.
Minimum Educational C++
I go through various style guides and attempt to extract the minimum C++ someone can learn to be functional on many code bases, and in your own code.