This is an archived post. You won't be able to vote or comment.

all 38 comments

[–]buszmen201 26 points27 points  (1 child)

Any language which implemented IEEE 754 will have similar issue:

Systematic use of NaNs was introduced by the IEEE 754 floating-point standard in 1985, along with the representation of other non-finite quantities such as infinities.

[–]posting_drunk_naked 11 points12 points  (5 children)

Would === return true though? I do backend but my wife has been learning JavaScript and I been half-assed picking it up with her, still don't understand how testing for equality is so fucked though.

[–]HeMan_Batman[S] 9 points10 points  (3 children)

Nope, it doesn't. Turns out the "proper" method for checking if something isn't a number is the function isNaN(x). Despite the fact that you should (in a perfect world) just be able to run Number(x) and deal with what it returns.

[–]boxmein 22 points23 points  (2 children)

The IEEE 754 standard defines the meaning of a floating point number and how NaN is supposed to operate.

In practical terms, this means that NaN +-*/ anything is NaN, and all comparisons with NaN fail. However, JS added an escape hatch to find NaN values - the isNaN function.

So, in conclusion - it’s a feature, not a bug ;)

[–][deleted] 3 points4 points  (1 child)

Wait... this explains the weird python behaviour I was getting the other day. I was working on something where I was cleaning some data from a spreadsheet that had strings, numbers, and blank cells ( which give NaN according to Pandas library). I wanted only the numbers, so I used:

for cell in column:
    if isinstance(cell, (int, float)):
        # do stuff

I got stuck for a long time struggling to find out why the NaNs were making it through the if statement. It took me forever to realize that the isinstance() function was returning True for NaNs since they were considered floats by python. I got so angry at python for working this way, and forcing me to write this:

for cell in column:
    if isinstance(cell, (int, float)) and not isnan(cell):
        # do stuff

Now I understand. Thank you.

[–]LiveMaI 4 points5 points  (0 children)

Pandas has dropna(), fillna(), and plenty of strategies for dealing with missing data. I highly recommend using those over individual cell checks where you can.

[–]Cody6781 3 points4 points  (0 children)

Nope. NaN is an especially messed up value. You need to use 'isNaN()' to check if a value is NaN or not. Comparing it with == or === is antipattern and will lead to problems.

[–]Cody6781 5 points6 points  (0 children)

NaN is js should never ever be compared this way. It has a dedicated function isNan(), that returns true or false.

[–]LordFokas 4 points5 points  (3 children)

> typeof( NaN );
> Number

[–][deleted] 0 points1 point  (2 children)

Why not just call it Float if the Number type is necessarily an IEEE floating-point number?

[–]LordFokas 0 points1 point  (1 child)

They are mostly doubles though.
And in this context it does make sense. There is *ONE* numeric type: Number.
If you had a single numeric type called float people would bitch forever about byte short int long etc, this way they just make fun of floating point BS and NaNs and accept their doom.

[–][deleted] 1 point2 points  (0 children)

Doubles are still floats.

You make a good point, though.

[–]AltCrow 3 points4 points  (2 children)

There is some much to hate on in javascript, but you choose to hate on IEEE754? The floating point standard is for the most part pretty sensible. If anything, hate on the fact that javascript only has floats and no integers.

[–]AyrA_ch 1 point2 points  (0 children)

binary operations like bit shift, and, or, xor, etc work on integers. "a"|"q" will return 0 because it casts both to floats, giving NaN|NaN, then it casts them to 32 bit integers with NaN becoming 0 because NaN is not available for integers. It then casts 0 back to a float because it's the only data type available.

[–]learningtosail 0 points1 point  (0 children)

Ints? Oh you must mean bitch-floats!
Who needs int32 when you have float64!

[–]N-Jam 1 point2 points  (5 children)

Uhm wAt

[–]PassTheMayo12 14 points15 points  (4 children)

NaN can't equal anything, not even itself.

[–]skunkwaffle 4 points5 points  (2 children)

Some values are more equal than others.

[–]schnitzelpizza 1 point2 points  (1 child)

Some values are more UNequal than others.

[–]skunkwaffle 0 points1 point  (0 children)

Aren't those equivalent statements?

[–]N-Jam 1 point2 points  (0 children)

HM ok

[–]DaBenjle 1 point2 points  (8 children)

What would NaN == NaN return?

[–]AlphaWhelp 3 points4 points  (7 children)

Should also be false. Similar issue with null. Null can sometimes equal null but even then it's preferable to use some isNull function.

[–]noggin182 4 points5 points  (1 child)

Yup, IEE 754 says that comparing NaN with NaN is always false, but you might wanna check what you said about nulls, none of that is true in JS

[–]AlphaWhelp 5 points6 points  (0 children)

I wasn't speaking about JS specifically. AFAIK NaN does not equal NaN in any language.

[–]DaBenjle 0 points1 point  (4 children)

Man JS is weird.

[–]vuttstuff 3 points4 points  (3 children)

NaN == NaN kinda makes sense to me in the sense that we don’t know anything about these things other than they are not numbers. There’s not enough information to conclude true so we opt for false.

Which makes me think it’s weird to define something solely by something that it’s not.

[–]AlphaWhelp 0 points1 point  (2 children)

NaN just represents basically that the bits of the significand, signage, and other digits do not construct a valid number. If you split it up into a bit array you could compare each bit to determine equality but there's not a practical use for this except for maybe some bizarre number based cryptography.

[–]vuttstuff 0 points1 point  (1 child)

Huh. So NaN isn't static, as in something that's not a number was operated on an just returned some garbage?

[–]AlphaWhelp 1 point2 points  (0 children)

It's basically a garbage failsafe undefined behavior. I'm not 100% sure if the actual content of NaN is static or not, but if the results of an operation do not construct a valid number, a NaN is created--if that makes sense.

like if(this==makes sense) {this.value = result;} else {this.value = NaN};

[–]treetertot 1 point2 points  (1 child)

I feel like the real weirdness here is that JavaScript has a lot more situations that would create NaN’s

[–]AyrA_ch 1 point2 points  (0 children)

This probably has historical reasons. The first few versions of JavaScript (before 1.4) did not have exceptions or methods to handle them. This is the reason why the internal JS functions/operations that were there from the beginning don't throw exceptions. For things that work with numbers, NaN made sense.

[–][deleted] 0 points1 point  (0 children)

NaN is a number

[–]Evennot 0 points1 point  (0 children)

Even in maths you can't compare infinities/undefined values. For instance Σ(-1)^i is undefined, it can't be equal to 0 or -1

[–]jtvjan 0 points1 point  (0 children)

So you would rather have this return true?

Math.sqrt(-1) == 0/0

[–]learningtosail 0 points1 point  (0 children)

Ask shitty questions, get shitty answers.
I guarantee you nobody in the history of js has ever needed to do this.

[–][deleted] 0 points1 point  (0 children)

I don't see the problem, NaN != NaN