9

How can this be false?

console.log(parseInt(undefined));
//NaN
console.log(parseInt(undefined)===NaN);
//false

That seems dumb

8DK
  • 704
  • 1
  • 5
  • 15

3 Answers3

9

NaN is not equal to anything, even itself. Use isNaN to detect NaN instead of an equality.

NaN === NaN  // -> false
isNaN(NaN)   // -> true (argument is coerced [ToNumber] as required)
x = NaN
x !== x      // -> true (would be false for any other value of x)
NaN || "Hi"  // -> "Hi" (NaN is a false-y value, but not false)

This is a result of JavaScript following IEEE-754 and it's (quiet) NaN lack-of-ordering behavior:

A comparison with a NaN always returns an unordered [not equal] result even when comparing with itself.

See also What is the rationale for all comparisons returning false for IEEE754 NaN values?

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 1
    is it part of quantum physics? – 8DK Sep 07 '14 at 19:07
  • So this is expected behavior! That explains why I haven't noticed it in all of the [wtf](http://wtfjs.com/) [javascript](https://www.destroyallsoftware.com/talks/wat) content I've viewed. – iabw Sep 07 '14 at 19:10
  • @iabw Yes, it is expected. I think it is that a direct check comes up rather infrequently. Most code likely coerces the result of such a parseInt as 0 or considers 0/false-y to be invalid (as NaN is still a flase-y value). Also, this NaN behavior wouldn't (shouldn't) surprise people with background in other languages using similar floating point types, which is most of them. – user2864740 Sep 07 '14 at 19:18
3

Its because NaN === NaN is also false!

Nabi
  • 304
  • 2
  • 8
3

NaN is not equal to itself and the reason can be understood from the answer posted by Stephen here:

My understanding from talking to Kahan is that NaN != NaN originated out of two pragmatic considerations:

  • that x == y should be equivalent to x - y == 0 whenever possible (beyond being a theorem of real arithmetic, this makes hardware implementation of comparison more space-efficient, which was of utmost importance at the time the standard was developed — note, however, that this is violated for x = y = infinity, so it’s not a great reason on its own; it could have reasonably been bent to x - y == 0 or NaN).

  • more importantly, there was no isnan( ) predicate at the time that NaN was formalized in the 8087 arithmetic; it was necessary to provide programmers with a convenient and efficient means of detecting NaN values that didn’t depend on programming languages providing something like isnan( ) which could take many years. I’ll quote Kahan’s own writing on the subject:

Were there no way to get rid of NaNs, they would be as useless as Indefinites on CRAYs; as soon as one were encountered, computation would be best stopped rather than continued for an indefinite time to an Indefinite conclusion. That is why some operations upon NaNs must deliver non-NaN results. Which operations? … The exceptions are C predicates “ x == x ” and “ x != x ”, which are respectively 1 and 0 for every infinite or finite number x but reverse if x is Not a Number ( NaN ); these provide the only simple unexceptional distinction between NaNs and numbers in languages that lack a word for NaN and a predicate IsNaN(x).

Note that this is also the logic that rules out returning something like a “Not-A-Boolean”. Maybe this pragmatism was misplaced, and the standard should have required isnan( ), but that would have made NaN nearly impossible to use efficiently and conveniently for several years while the world waited for programming language adoption. I’m not convinced that would have been a reasonable tradeoff.

Community
  • 1
  • 1
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331