NaN, the not-a-number number that isn't NaN
> 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.
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!
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.
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).
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)
I get the idea behind NaN != NaN, but has there ever been any instance where this design decision has made practical code better instead of becoming a tripping hazard and requiring extensive special casing?
I'm also not a fan of the other property that NaN evaluates to false for all three of <, > and =, even though I don't have a good idea what to do otherwise.
I think as programmers, we usually assume that "not (a > b)" implies "a <= b" and vice-versa and often rely on that assumption implicitly. NaN breaks that assumption, which could lead to unexpected behavior.
Consider something like this (in JS) :
function make_examples(num_examples) {
if (num_examples <= 0) {
throw Error("num_examples must be 1 or more");
}
const examples = [];
for (let i = 0; i < num_examples; i++) {
examples.push(make_example(i));
}
// we assume that num_examples >= 1 here, so the loop ran at least once and the array cannot be empty.
postprocess_first_example(examples[0]); // <-- (!)
return examples;
}
If somehow num_examples were NaN, the (!) line would fail unexpectedly because the array would be empty.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.
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...
console.log(new Array(16).join("wat"-1) + " Batman!")
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)
Also, NaN is the only value in JS that isn't === to itself, so if for some reason you want to test for strict value identity with the value NaN of type number, that's one way to do it:
if(x !== x) ... // x is NaN
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
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.
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.
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`
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.
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”.
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.
Slightly off topic, I hate that typescript bundles NaN under the number type and the signature for parseInt is number.
See also: Tom7's "NaN gates and Flip FLOPS": https://www.youtube.com/watch?v=5TFDG-y-EHs
Imagine that society calls the people who have to work with these toys during office hours, engineers
> type(NaN) -> "number"
NaN should have been NaVN, not a valid number.
> 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.