5 ms·
Javascript's NaN
- beering 14y agoOne wonders if this blog post would have been written at all if the author was familiar with NaN in floating-point numbers and knew that isNaN was a thing. isNaN is the defined method of checking if something Not A Number or can't be converted into a number. The Real WTF (and infamous "feature" of JS) is that many things can be converted into a number. isNaN("string") => true isNaN({}) => true but you might not expect that isNaN("3e2") => false isNaN("") => false isNaN([]) => false
- mbrubeck 14y agoThe "Harmony" proposal for the next JavaScript spec includes Number.isNaN, which is meant to be a less-confusing version (with no type coercion). It's currently implemented in Firefox Nightly builds: http://bugzil.la/749818 http://bugzil.la/749818 Number.isNaN(NaN) => true Number.isNaN(3e2) => false Number.isNaN("NaN") => false Number.isNaN("string") => false Number.isNaN({}) => false Number.isNaN("3e2") => false Number.isNaN([]) => false http://wiki.ecmascript.org/doku.php?id=harmony:number.isnan http://wiki.ecmascript.org/doku.php?id=harmony:number.isnan
- JeremyBanks 14y agoI wonder how many blog posts could have been avoided if Number had just been named Float instead.
- Skalman 14y agoI think "Number" is a better name than "Float". It's a much more common word which I immediately get a feeling for. That typeof NaN === 'number' really makes sense for me, and I feel that most wouldn't need a long explanation to get it either.
- JeremyBanks 14y agoI actually do agree that Number is a better name -- particularly for a language that's many people's first experience with programming these days. My comment was a tad sarcastic. Though if they're not calling them floats, maybe they could have also come up with a better name for NaN. If they used, say, "ERR", it would be something many people had seen before (from calculators) and we'd get to stop hearing people bitch about "NotANumber is a number WTF". (I suppose "they" in this case must be the hypothetical well-treated team that didn't develop JavaScript instead of a frustrated Brendan Eich.)
- cygx 14y agoJavascript's numeric type mixes floating point and integer semantics (bitops!), so Number is appropriate.
- jensnockert 14y agoYet another post that underestimates the importance on NaN, it isn't 'WTF' at all if you understand its design. Sure, the naming in ES makes it a bit silly since NaN is a number, but it is something you only have to see once to understand. Don't mess with IEEE 754, it is almost universally adopted for binary floating-point for very good reasons.
- elliptic 14y agoNaN is incredibly useful, but I'm not so sure that 1/"a" = NaN is a great idea.
- grayrest 14y agoStrings that arent numeric are type coerced into NaN. Using unary plus to coerce to number: +"2" is the primitive number 2 while +"a" is NaN and per the floating point spec, any arithmetic operation on NaN results in NaN. The correct though unintuitive way to check for NaN is `(x === x) === false`. NaN is a number per the IEEE 754. The majority of Javascript WTFs are due to type coercion. Use triple equals and check your inputs to avoid.
- some-1 14y agoNo, the correct way is to use the global function isNaN(x);
- grayrest 14y agoisNaN will return true for NaN and all values that coerce to it. The equals check will test ONLY for NaN itself: var x = "a"; isNaN(x); // true (x === x) === false // false x = NaN isNaN(x); // true (x === x) === false // true
- dap 14y agoYes, it's goofy that typeof (NaN) == 'number'. But it's not that unreasonable to have a numeric value that's explicitly invalid. Pointers and references in other languages have null, which is a legal value for any type of object, but is explicitly invalid if used as an object. Also, isNaN is global.
- SeanLuke 14y ago> Yes, it's goofy that typeof (NaN) == 'number'. You should be harsher on him. NaN is definitely a number in practically every programming language. (type-of (/ 0.0 0.0)) SINGLE-FLOAT System.err.println((new Double(0.0/0.0)) instanceof Number) true from types import * type(1e10000 / 1e10000) <type 'float'> It looks like the blogger is just out and out mistaken. But there's more. The poster goes on about NaN not being easy to check for: not realizing that it's the only value which is never equal to itself. He even thinks this is a bug.
- halbermensch 14y agoOr not goofy, if you think of 'number' as an enum constant denoting that variable's type, rather than its value. In this context, 'NaN' just happens to be another admissible value within the space of "number".
- deleted 14y ago[deleted]
- tikhonj 14y agoOf all the things to complain about, he chose one that is not JavaScript's fault: the fact that NaN is a number and equality on NaN is not reflexive is a property of the floating point number standard. Try it in some other language you have lying around, like Python: >>> type(float('nan')) <type 'float'> >>> float('nan') == float('nan') False Also Haskell: Prelude> 0/0 NaN Prelude> 0/0 == 0/0 False If anything, it's refreshing that JavaScript does behave like other languages in this case!
- simonster 14y agoThe language-agnostic way to check for NaN is to check whether x != x. Some languages might also need a type check, but AFAIK JS isn't one of them.
- dreish 14y agoThis is hardly a JavaScript quirk. In Clojure: hackclj.core=> Double/NaN NaN hackclj.core=> (== Double/NaN Double/NaN) false hackclj.core=> (= Double/NaN Double/NaN) false hackclj.core=> (.equals Double/NaN Double/NaN) true hackclj.core=> (identical? Double/NaN Double/NaN) false hackclj.core=> (type Double/NaN) java.lang.Double hackclj.core=> (number? Double/NaN) true In Perl (which doesn't have a concept of a number type distinct from other scalars such as strings, but we can see that it participates in addition differently from non-numeric scalars, which behave like 0): DB<1> $inf = 1e300 * 1e300 DB<2> $nan = $inf - $inf DB<3> print $nan nan DB<4> print ($nan == $nan) DB<5> print ref($nan) DB<6> print $nan+1 nan In Ruby: irb(main):001:0> inf = 1e300*1e300 => Infinity irb(main):002:0> nan = inf-inf => NaN irb(main):003:0> nan == nan => false irb(main):004:0> nan.class => Float Python 2.7.3 (much earlier versions got equality wrong, claiming nan == nan): >>> inf = 1e300*1e300 >>> nan = inf-inf >>> nan nan >>> nan == nan False >>> type(nan) <type 'float'>