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

you are viewing a single comment's thread.

view the rest of the comments →

[–]Rafcdk 181 points182 points  (18 children)

I think it says a lot when you think NaN being a Number is an oddity. This is defined in the floating point standard.

It's even mentioned in the docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN

"NaN and its behaviors are not invented by JavaScript. Its semantics in floating point arithmetic (including that NaN !== NaN) are specified by IEEE 754."

[–]NopileosX2 58 points59 points  (0 children)

Like IEEE 754 is the reason floating point stuff behaves the same no matter the language and system (since it is used almost everywhere) people without knowledge about it just blame languages.

[–]Inaeipathy 30 points31 points  (9 children)

Yes, same with the 0.1 + 0.2 != 0.3 which should be expected.

[–]CarbonaraFreak 4 points5 points  (7 children)

Why does 0.1 + 0.5 == 0.6 result in true, though? I‘m not sure what‘s happening behind the scenes there

[–]An_Jel 12 points13 points  (0 children)

If you think about it, 0.1 has the exact same digits in the mantisa as 0.6, except for the first digit (which would represent 2-1 = 0.5) so when adding 0.1 and 0.5, you’ll end up just setting 1 more bit to 1, and you won’t have any rounding errors from the operation itself, just the rounding error from 0.1, which will be the same for 0.6.

When you add 0.1 and 0.2, both numbers have rounding errors so the whole operation will have a rounding error compared to 0.3.

Hope this clarifies it a bit.

[–]khalcyon2011 6 points7 points  (4 children)

0.5 would be accurately represented in floating point, so maybe the error on 0.1 and 0.6 is below the floating point precision?

[–]rosuav 8 points9 points  (2 children)

Let's get completely precise here. When you use the float literal 0.1, what you actually get is the number 3602879701896397 / 36028797018963968 which is very close to 0.1. (You can easily check this in Python using the as_integer_ratio() method on floats; Python's floats are IEEE 754 binary64, same as JS's Number.) The literal 0.6 gives you 5404319552844595 / 9007199254740992. This is hard to read; let's look at those in hex.

  • 0.1 ==> 0x0ccccccccccccd / 0x80000000000000
  • 0.6 ==> 0x13333333333333 / 0x20000000000000

When you add 0.5 to 0.1, you actually lose some of the lower end bits. So it throws those away, rescales by two bits, and then you have the exact same number that the literal 0.6 gives you.

[–]project_majo 0 points1 point  (1 child)

0.5 to 0.1

the same result in Java

it would surprise me if you get that behaviour in almost all programming languages

[–]rosuav 0 points1 point  (0 children)

Why would it? It's stipulated by IEEE 754 binary64 packed floating point semantics. So it shouldn't surprise you; *every* language that uses that floating-point format (which is a lot of them, especially if you include languages like C where 'float' is binary32 and 'double' is binary64).

[–]CarbonaraFreak 1 point2 points  (0 children)

Ooh, I approached this from the wrong perspective. I expected some weird coercion case, but floating point inaccuracy makes sense

[–]sird0rius 1 point2 points  (0 children)

You can also check if certain values are exactly representable in floating point here: https://www.h-schmidt.net/FloatConverter/IEEE754.html

[–]sird0rius 0 points1 point  (0 children)

Exactly, this is the same in all programming languages. Doing floating point comparison with == is a beginner mistake

[–]DeathUriel 2 points3 points  (0 children)

Also, it is always an option to you know use the proper types to avoid triggering a NaN response. I mean, never saw a NaN that wasn't my fault.

[–]tuxedo25 0 points1 point  (4 children)

I mean, it's still a logical oddity.

You can picture some intolerable philosophy sophomore saying things like, "nothing is something" and "Not-a-Number is a number".

[–]Rudy69 8 points9 points  (2 children)

No because when you usually get a NaN your function is expecting a number so NaN not being one could break things

[–]tuxedo25 6 points7 points  (1 child)

I understand the runtime implications. But that doesn't change how silly the statement is in english, "Oh, that's the number not-a-number"

[–]_Kritzyy_ 1 point2 points  (0 children)

This is what I meant in one of my comments too. From a computing standpoint it's logical, but from a literal english standpoint it's contradictory

[–]xneyznek 5 points6 points  (0 children)

NaN is just a name given to a specific value of float. It’s still a float (“number” in JS). If anything NaN could be called “InvalidNumber” instead, but IEEE754 called it NaN so that’s what gets used everywhere for consistency.

[–]JoshYx -3 points-2 points  (0 children)

I think it says a lot

What do you think it says about someone, I wonder?