console.log(
0 / 0,
Infinity / Infinity,
0 * Infinity,
Infinity - Infinity
);
> NaN NaN NaN NaN
console.log(
Math.sqrt(-1),
Math.log(-1),
Math.acos(2),
Math.asin(2)
);
> NaN NaN NaN NaN
console.log(
parseInt('hello'), parseFloat('world'),
Number(undefined), Number({}),
+undefined, +{},
+new Date('hello')
);
> NaN NaN NaN NaN NaN NaN NaN
console.log(NaN);
> NaN
... a particular JavaScript value.
(very particular)
console.log(typeof NaN);
> number
...a Number.
console.log(NaN === NaN);
> false
...not "Not a Number".
var assert = require('assert');
assert.equal(NaN, NaN);
> AssertionError: NaN == NaN
...tricky to test.
console.log(isNaN(NaN));
> true
console.log(isNaN('foo'), isNaN(['bar']), isNaN({}));
> true true true
console.log(typeof 'foo', typeof ['bar'], typeof {});
> string object object
function myIsNaN(x) {
return typeof x === 'number' && isNaN(x);
}
console.log([NaN, 'foo', ['bar'], {}].map(isNaN));
console.log([NaN, 'foo', ['bar'], {}].map(myIsNaN));
> true true true true
> true false false false
function myIsNaN(x) {
return x !== x;
}
console.log([NaN, 'foo', ['bar'], {}].map(isNaN));
console.log([NaN, 'foo', ['bar'], {}].map(myIsNaN));
> true true true true
> true false false false
This works because NaN
is the only value in JavaScript for which the equality operators are non-reflexive.
console.log([NaN, 'foo', ['bar'], {}].map(isNaN));
console.log([NaN, 'foo', ['bar'], {}].map(Number.isNaN));
...and it does what we want:
> true true true true
> true false false false
console.log([NaN, 'foo', ['bar'], {}].map(isNaN));
console.log([NaN, 'foo', ['bar'], {}].map(n => Object.is(n, NaN)));
> true true true true
> true false false false
This uses the SameValue
internal operation, which is (mostly) like how a Set
distinguishes its elements.
pow(2, 3) -> 8
pow(-1, 1.5) -> NaN
pow(NaN, anything) -> NaN
pow(anything, NaN) -> NaN
If either input is NaN
, or if the base is negative and the exponent is not an integer, the result is NaN
.
pow(0, 0) -> 1
pow(Infinity, 0) -> 1
pow(1, Infinity) -> 1
This behavior is inherited from C99 and POSIX 2001.
Most languages follow this.
[0 ** 0, float("inf") ** 0, 1 ** float("inf")]
> [1 1.0 1.0]
[0 ** 0, Float::INFINITY ** 0, 1 ** Float::INFINITY]
> [1 1.0 1.0]
print(math.pow(0, 0), math.pow(math.huge, 0), math.pow(1, math.huge))
> 1 1 1
Math.pow(0, 0);
Math.pow(0, 0);
> 1
Math.pow(0, 0);
> 1
Math.pow(Infinity, 0);
Math.pow(0, 0);
> 1
Math.pow(Infinity, 0);
> 1
Math.pow(0, 0);
> 1
Math.pow(Infinity, 0);
> 1
Math.pow(1, Infinity);
Math.pow(0, 0);
> 1
Math.pow(Infinity, 0);
> 1
Math.pow(1, Infinity);
> NaN
#[fit] Why?
- ES
1
specifiespow
: 1997 - C99 specifies
pow
: 1999 - POSIX specifies
pow
: 2001 - IEEE 754 inherits
pow
: 2008
#[fit] Backwards #[fit] compatibility
0 10000000 01000000000000000000000
- 1-bit sign
- 8-bit exponent, offset by
127
- 23-bit significand (with implicit leading 24th bit)
(-1) ^ s * 2 ^ (exp - 127) * 1.significand
0 10000000 01000000000000000000000
(-1) ^ 0 = 1
2 ^ (10000000b - 127) = 2
1.01b = 1.25
1 * 2 * 1.25 = 2.5
0 11111111 00000000000000000000000 -> Infinity
1 11111111 00000000000000000000000 -> -Infinity
Infinity values have a maximized exponent and a zero significand.
0 11111111 10000000000000000000000 -> NaN
NaN values have a maximized exponent and a nonzero significand.
1 11111111 10000000000000000000000 -> NaN (quiet, negative)
0 11111111 10000000000000000000001 -> NaN (quiet, but different)
0 11111111 00000000000000000000001 -> NaN (signaling)
0 11111111 00000000000000000000010 -> NaN (signaling, but different)
0 11111111 00000000000000000000011 -> NaN (we can start counting!)
1 11111111 10000000000000000000000 -> NaN (quiet, negative)
0 11111111 10000000000000000000001 -> NaN (quiet, but different)
0 11111111 00000000000000000000001 -> NaN (signaling)
0 11111111 00000000000000000000010 -> NaN (signaling, but different)
0 11111111 00000000000000000000011 -> NaN (we can start counting!)
How many NaNs are there, really?
Thus, NaN !== NaN1.
- http://ariya.ofilabs.com/2014/05/the-curious-case-of-javascript-nan.html
- http://www.2ality.com/2012/02/nan-infinity.html
- https://en.wikipedia.org/wiki/NaN
- https://tc39.github.io/ecma262/#sec-applying-the-exp-operator
- I'm Lewis J Ellis: @lewisjellis on Twitter and GitHub
- My website is LewisJEllis.com.
- Slides available at GitHub.com/LewisJEllis/nantalk
Footnotes
-
With probability
1/9,007,199,254,740,990
. ↩