NaN is Not a Math

A critique of the counter-claim that JavaScript's use of NaN errors is valid because it's 'math.'

Reposted from Learn JS the Hard Way By Zed A. Shaw

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

Exploring the Replacement for C as an Educational Language

My thoughts so far on finding a replacement for C in teaching compiled languages and memory safety.

ResearchPublished Apr 20, 2024

How to Read Programmer Documentation

An excerpt from Learn Python the Hard Way, 5th Edition that explains how I analyze learn from projects with poor or no documentation (which is most of them).

PythonPublished July 29, 2023

The 5 Simple Rules to the Game of Code

An experimental idea to teach the basics of a Turing machine before teaching loops and branching. Feedback welcome.

PythonPublished July 29, 2023

Announcing _Learn Python the Hard Way_'s Next Edition

Announcing the new version of _Learn Python the Hard Way_ which will be entirely focused on Pre-Beginner Data Science and not web development.

AnnouncementPublished May 11, 2023