Idiosyncrasies of NaN @LewisJEllis

"NaN" stands for: Not a Number

What kinds of things give us NaN?

Fuzzy math console.log( 0 / 0, Infinity / Infinity, 0 * Infinity, Infinity - Infinity ); > NaN NaN NaN NaN

Complex Numbers console.log( Math.sqrt(-1), Math.log(-1), Math.acos(2), Math.asin(2) ); > NaN NaN NaN NaN

Turning things into Numbers console.log( parseInt('hello'), parseFloat('world'), Number(undefined), Number({}), +undefined, +{}, +new Date('hello') ); > NaN NaN NaN NaN NaN NaN NaN

What is NaN? (in JavaScript)

"Not a Number" is... console.log(NaN); > NaN

... a particular JavaScript value. (very particular)

"Not a Number" is... console.log(typeof NaN); > number

...a Number.

"Not a Number" is... console.log(NaN === NaN); > false

...not "Not a Number".

"Not a Number" is... var assert = require('assert'); assert.equal(NaN, NaN); > AssertionError: NaN == NaN

...tricky to test.

"NaN" actually stands for: Not a NaN

So we know where NaN appears, but how do we tell if something is NaN?

Easy! Just use the isNaN function: console.log(isNaN(NaN)); > true

Or maybe not... console.log(isNaN('foo'), isNaN(['bar']), isNaN({})); > true true true console.log(typeof 'foo', typeof ['bar'], typeof {}); > string object object

So let's just make our own: 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

Or we can recall "Not a NaN": 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.

Fortunately, ES2015 adds Number.isNaN: 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

Or we can use Object.is: 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.

But NaN isn't just a JavaScript thing!

NaN is actually defined by the IEEE 754 floating-point standard.

If you know where NaN appears and how it behaves in one language, that carries over to most others.

Most.

Fun fact about that...

The IEEE 754 spec defines the pow function: 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.

Three indeterminate forms of pow: 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.

Here's what Python does: [0 ** 0, float("inf") ** 0, 1 ** float("inf")] > [1 1.0 1.0]

And Ruby: [0 ** 0, Float::INFINITY ** 0, 1 ** Float::INFINITY] > [1 1.0 1.0]

And Lua: print(math.pow(0, 0), math.pow(math.huge, 0), math.pow(1, math.huge))

> 1 1 1

But JavaScript?

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

Why?

4 ES1 specifies pow: 1997 4 C99 specifies pow: 1999 4 POSIX specifies pow: 2001 4 IEEE 754 inherits pow: 2008

So just like every other question about JavaScript, the answer is...

Backwards compatibility

So anyway, what does IEEE 754 say about how we represent NaN?

Bit representation of a float32 value: 0 10000000 01000000000000000000000

4 1-bit sign 4 8-bit exponent, offset by 127 4 23-bit significand (with implicit leading 24th bit) 4 (-1) ^ s * 2 ^ (exp - 127) * 1.significand

Example float32 value: 0 10000000 01000000000000000000000

4 (-1) ^ 0 = 1 4 2 ^ (10000000b - 127) = 2 4 1.01b = 1.25 4 1 * 2 * 1.25 = 2.5

Bit representations of special values: 0 11111111 00000000000000000000000 -> Infinity 1 11111111 00000000000000000000000 -> -Infinity

Infinity values have a maximized exponent and a zero significand.

Bit representations of special values: 0 11111111 10000000000000000000000 -> NaN

NaN values have a maximized exponent and a nonzero significand.

So these are also all NaN: 1 0 0 0 0

11111111 11111111 11111111 11111111 11111111

10000000000000000000000 10000000000000000000001 00000000000000000000001 00000000000000000000010 00000000000000000000011

-> -> -> -> ->

NaN NaN NaN NaN NaN

(quiet, negative) (quiet, but different) (signaling) (signaling, but different) (we can start counting!)

So these are also all NaN: 1 0 0 0 0

11111111 11111111 11111111 11111111 11111111

10000000000000000000000 10000000000000000000001 00000000000000000000001 00000000000000000000010 00000000000000000000011

-> -> -> -> ->

NaN NaN NaN NaN NaN

How many NaNs are there, really?

(quiet, negative) (quiet, but different) (signaling) (signaling, but different) (we can start counting!)

2^24 - 2 = 16,777,214

And that's just with a float32! What about a double64?

2^53 - 2 = 9,007,199,254,740,990

That's 9 * 10^15, or 9 quadrillion. 9 petabytes is about 20,000 years worth of music.

If there are so many different possible NaNs, then it only seems reasonable...

...that one random NaN is unlikely to be the same as another random NaN!

Thus, NaN !== NaN . 1

1

With probability 1/9,007,199,254,740,990.

Some Related Links 4 http://ariya.ofilabs.com/2014/05/the-curious-caseof-javascript-nan.html 4 http://www.2ality.com/2012/02/nan-infinity.html 4 https://en.wikipedia.org/wiki/NaN 4 https://tc39.github.io/ecma262/#sec-applying-theexp-operator

Who are you and where can I find the slides? 4 I'm Lewis J Ellis: @lewisjellis on Twitter and GitHub 4 My website is LewisJEllis.com. 4 Slides available at GitHub.com/LewisJEllis/nantalk

console.log(NaN) - GitHub

So let's just make our own: function myIsNaN(x) { ... Or we can recall "Not a NaN": function myIsNaN(x) { .... 4 My website is LewisJEllis.com. 4 Slides available at ...

5MB Sizes 2 Downloads 209 Views

Recommend Documents

GitHub
domain = meq.domain(10,20,0,10); cells = meq.cells(domain,num_freq=200, num_time=100); ...... This is now contaminator-free. – Observe the ghosts. Optional ...

GitHub
data can only be “corrected” for a single point on the sky. ... sufficient to predict it at the phase center (shifting ... errors (well this is actually good news, isn't it?)

Torsten - GitHub
Metrum Research Group has developed a prototype Pharmacokinetic/Pharmacodynamic (PKPD) model library for use in Stan 2.12. ... Torsten uses a development version of Stan, that follows the 2.12 release, in order to implement the matrix exponential fun

Untitled - GitHub
The next section reviews some approaches adopted for this problem, in astronomy and in computer vision gener- ... cussed below), we would question the sensitivity of a. Delaunay triangulation alone for capturing the .... computation to be improved fr

ECf000172411 - GitHub
Robert. Spec Sr Trading Supt. ENA West Power Fundamental Analysis. Timothy A Heizenrader. 1400 Smith St, Houston, Tx. Yes. Yes. Arnold. John. VP Trading.

Untitled - GitHub
Iwip a man in the middle implementation. TOR. Andrea Marcelli prof. Fulvio Risso. 1859. Page 3. from packets. PEX. CethernetDipo topo data. Private. Execution. Environment to the awareness of a connection. FROG develpment. Cethernet DipD tcpD data. P

BOOM - GitHub
Dec 4, 2016 - 3.2.3 Managing the Global History Register . ..... Put another way, instructions don't need to spend N cycles moving their way through the fetch ...

Supervisor - GitHub
When given an integer, the supervisor terminates the child process using. Process.exit(child, :shutdown) and waits for an exist signal within the time.

robtarr - GitHub
http://globalmoxie.com/blog/making-of-people-mobile.shtml. Saturday, October ... http://24ways.org/2011/conditional-loading-for-responsive-designs. Saturday ...

MY9221 - GitHub
The MY9221, 12-channels (R/G/B x 4) c o n s t a n t current APDM (Adaptive Pulse Density. Modulation) LED driver, operates over a 3V ~ 5.5V input voltage ...

fpYlll - GitHub
Jul 6, 2017 - fpylll is a Python (2 and 3) library for performing lattice reduction on ... expressiveness and ease-of-use beat raw performance.1. 1Okay, to ... py.test for testing Python. .... GSO complete API for plain Gram-Schmidt objects, all.

article - GitHub
2 Universidad Nacional de Tres de Febrero, Caseros, Argentina. ..... www-nlpir.nist.gov/projects/duc/guidelines/2002.html. 6. .... http://singhal.info/ieee2001.pdf.

PyBioMed - GitHub
calculate ten types of molecular descriptors to represent small molecules, including constitutional descriptors ... charge descriptors, molecular properties, kappa shape indices, MOE-type descriptors, and molecular ... The molecular weight (MW) is th

MOC3063 - GitHub
IF lies between max IFT (15mA for MOC3061M, 10mA for MOC3062M ..... Dual Cool™ ... Fairchild's Anti-Counterfeiting Policy is also stated on ourexternal website, ... Datasheet contains the design specifications for product development.

MLX90615 - GitHub
Nov 8, 2013 - of 0.02°C or via a 10-bit PWM (Pulse Width Modulated) signal from the device. ...... The chip supports a 2 wires serial protocol, build with pins SDA and SCL. ...... measure the temperature profile of the top of the can and keep the pe

Covarep - GitHub
Apr 23, 2014 - Gilles Degottex1, John Kane2, Thomas Drugman3, Tuomo Raitio4, Stefan .... Compile the Covarep.pdf document if Covarep.tex changed.

SeparableFilter11 - GitHub
1. SeparableFilter11. AMD Developer Relations. Overview ... Load the center sample(s) int2 i2KernelCenter ... Macro defines what happens at the kernel center.

Programming - GitHub
Jan 16, 2018 - The second you can only catch by thorough testing (see the HW). 5. Don't use magic numbers. 6. Use meaningful names. Don't do this: data("ChickWeight") out = lm(weight~Time+Chick+Diet, data=ChickWeight). 7. Comment things that aren't c

SoCsploitation - GitHub
Page 2 ... ( everything – {laptops, servers, etc.} ) • Cheap and low power! WTF is a SoC ... %20Advice_for_Shellcode_on_Embedded_Syst ems.pdf. Tell me more! ... didn't destroy one to have pretty pictures… Teridian ..... [email protected].

Datasheet - GitHub
Dec 18, 2014 - Compliant with Android K and L ..... 9.49 SENSORHUB10_REG (37h) . .... DocID026899 Rev 7. 10. Embedded functions register mapping .

Action - GitHub
Task Scheduling for Mobile Robots Using Interval Algebra. Mudrová and Hawes. .... W1. W2. W3. 0.9 action goto W2 from W1. 0.1. Why use an MDP? cost = 54 ...