NaN, the not-a-number number that isn't NaN

piccalil.li

77 points by tobr 7 days ago


KalMann - 6 hours ago

> That’s also the reason NaN !== NaN. If NaN behaved like a number and had a value equal to itself, well, you could accidentally do math with it: NaN / NaN would result in 1, and that would mean that a calculation containing a NaN result could ultimately result in an incorrect number rather than an easily-spotted “hey, something went wrong in here” NaN flag.

While I'm not really against the concept of NaN not equaling itself, this reasoning makes no sense. Even if the standard was "NaN == NaN evaluates to true" there would be no reason why NaN/Nan should necessarily evaluate to 1.

WalterBright - an hour ago

The D language default initializes floating point values to NaN. AFAIK, D is the only language that does that.

The rationale is that if the programmer forgets to initialize a float, and it defaults to 0.0, he may never realize that the result of his calculation is in error. But with NaN initialization, the result will be NaN and he'll know to look at the inputs to see what was not initialized.

It causes some spirited discussion now and then.

dragonwriter - 5 hours ago

> That’s also the reason NaN !== NaN. If NaN behaved like a number and had a value equal to itself, well, you could accidentally do math with it: NaN / NaN would result in 1,

So, by that logic, if 0 behaved like a number and had a value equal to itself, well, you could accidentally do math with it: 0 / 0 would result in 1...

But as it turns out, 0 behaves like a number, has a value equal to itself, you can do math with it, and 0/0 results in NaN.

andai - 7 hours ago

Shouldn't an operator on incompatible types return undefined? ;)

Equality on things that it doesn't make sense to compare returning false seems wrong to me. That operation isn't defined to begin with.

By shipping with undefined, JavaScript could have been there only language whose type system makes sense... alas!

jasonthorsness - 6 hours ago

NaNs aren't always equal to each other in their bit representation either, most of the bits are kept as a "payload" which is not defined in the spec it can be anything. I believe the payload is actually used in V8 to encode more information in NaNs (NaN-boxing).

nhatcher - 6 hours ago

Also remember that NaN is represented in multiple ways bitwise:

https://en.wikipedia.org/wiki/NaN

Also you even have different kinds of NaN (signalling vs quiet)

dreamcompiler - 5 hours ago

Equality is a very slippery mathematical relationship. This observation formed the genesis of modern Category Theory [0].

NaN is an error monad.

[0] https://www.ams.org/journals/tran/1945-058-00/S0002-9947-194...

tuyiown - 7 hours ago

NaN comes from parsing results or Infinity occurring in operations. I personally ends up more to use Number.isFinite(), which will be false on both occurrences when I need a real (haha) numeric answer.

Aardwolf - 3 hours ago

I'm sometimes wondering if a floating point format really needs to have inf, -inf and nan, or if a single "non finite" value capturing all of those would be sufficient

Zealotux - 7 hours ago

console.log(new Array(16).join("wat"-1) + " Batman!")

Terr_ - 2 hours ago

A similar issue occurs in SQL, where NULL != NULL. [0] In both bases, our typical "equals" abstraction has become too leaky, and we're left trying to grapple with managing different kinds of "equality" at the same time.

Consider the difference between:

1. "Box A contains a cursed object that the human mind cannot comprehend without being driven to madness. Does Box B also contain one? ... Yes."

2. "Is the cursed object in Box A the same as the one in Box B? ... It... uh..." <screaming begins>

Note that this is not the same as stuff like "1"==1.0, because we're not mixing types here. Both operands are the same type, our problem is determining their "value", and how we encode uncertainty or a lack of knowledge.

[0] https://en.wikipedia.org/wiki/Null_(SQL)

WalterBright - an hour ago

Another use for NaN's is, suppose you have an array of sensors. Given enough sensors, you're pretty much guaranteed that some of the sensors will have failed. So the array needs to continue to work, even if degraded.

A failed sensor can indicate this by submitting a NaN reading. Then, and subsequent operations on the array data will indicate which results depended on the failed sensor, as the result will be NaN. Just defaulting to zero on failure will hide the fact that it failed and the end results will not be obviously wrong.

wodenokoto - 6 hours ago

My gut reaction is that both NaN == NaN and NaN != NaN should be false, it to put it another way, NaN != NaN returns True was a surprise to me.

Does Numpy do the same? That’s where I usually meet NaN.

jraph - 7 hours ago

tl;dr:

- NaN is a floating point number, and NaN != NaN by definition in the IEEE 754-2019 floating point number standard, regardless of the programming language, there's nothing JavaScript-specific here.

- In JS Number.isNaN(v) returns true for NaN and anything that's not a number. And in JS, s * n and n * s return NaN for any non empty string s and any number n ("" * n returns 0). (EDIT: WRONG, sée below)

- 5 hours ago
[deleted]
kace91 - 7 hours ago

random thought: To see if something equals NaN,can't you just check for the stringified form of the number equaling "NaN"?

after all, the usual WTF lists for JS usually have a stringified NaN somewhere as part of the fun.

Szpadel - 7 hours ago

well there is also one weird quirk I I assumed will be also included in this article:

because a <= b is defined as !(a > b)

then:

5 < NaN // false

5 == NaN // false

5 <= NaN // true

Edit: my bad, this does not work with NaN, but you can try `0 <= null`

fwlr - 6 hours ago

Tangentially related: one of my favourite things about JavaScript is that it has so many different ways for the computer to “say no” (in the sense of “computer says no”): false, null, undefined, NaN, boolean coercion of 0/“”, throwing errors, ...

While it’s common to see groaning about double-equal vs triple-equal comparison and eye-rolling directed at absurdly large tables like in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid... but I think it’s genuinely great that we have the ability to distinguish between concepts like “explicitly not present” and “absent”.

candiddevmike - 4 hours ago

Slightly off topic, I hate that typescript bundles NaN under the number type and the signature for parseInt is number.

nph278 - 4 hours ago

See also: Tom7's "NaN gates and Flip FLOPS": https://www.youtube.com/watch?v=5TFDG-y-EHs

lnxg33k1 - 6 hours ago

Imagine that society calls the people who have to work with these toys during office hours, engineers

amelius - 7 hours ago

> type(NaN) -> "number"

NaN should have been NaVN, not a valid number.