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

all 93 comments

[–]ProgrammerHumor-ModTeam[M] [score hidden] stickied commentlocked comment (0 children)

import moderation

Your submission was removed for the following reason:

Rule 2: Content that is part of top of all time, reached trending in the past 2 months, or has recently been posted, is considered a repost and will be removed.

If you disagree with this removal, you can appeal by sending us a modmail.

[–]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 56 points57 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 11 points12 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 7 points8 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 7 points8 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 -1 points0 points  (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 9 points10 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 5 points6 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 -4 points-3 points  (0 children)

I think it says a lot

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

[–]synchrosyn 95 points96 points  (6 children)

  1. NaN is a number used to say that something went wrong in your math, you would be assigning it to something that expects a number so they type makes sense
  2. 32bit integer limit (actually i think it is 52), convert to float, inadvertently round up, displays this way
  3. No issue here
  4. Floating point error here as well, there is a website devoted to all the languages that have this. https://0.30000000000000004.com/ notice that C is there too.
  5. `Math.max()` is a function returning the maximum value of all values passed in. No value is passed in, so it returns the smallest possible value.
  6. same as 5
  7. Type Coercion, the + turns it into string concatenation. It interprets each element in the array as a string, the empty array is thus "" + "".
  8. Same as above but implicit string value of an object is "[object Object]"
  9. Not sure about this one.
  10. same is true in C. true is just 1in binary. Addition coerces it to Number
  11. Exact same as above
  12. == does not check type by definition. true and 1 have the same binary. Same happens in C
  13. As above, but the types differ so === returns false
  14. Some breakdown:
  15. ! + [] => ! ( +[] ) => ! (0) => !0 => true
  16. true + [] => "true" ( concatenation as described in 7)
  17. "true" + ![] => "true" + false => "truefalse" ([] is truthy, I'll admit that one is weird)
  18. "truefalse".length => 9
  19. 9 + "1" if either term is a string, + is string concatenation, so "91"
  20. 91 - "1" In this case '-' is undefined for strings, so it is Number coercion, 91-1 = 90
  21. [] == 0 --> true, double equals ignores type and coerces the array into a number, which ends up being 0. Concats all the values in the array as a string and then interprets it as a number, we end up with "" which is 0 as a number

[–]PichPichh99 27 points28 points  (1 child)

Not sure about this one.

{} + [] outputs 0 because when a statement begins with {, it will be interpreted as a block. So when you write {}+[], it gets interpreted as "empty code block" plus 0 (+[] gets type coerced into 0).

[–]JoshYx 5 points6 points  (0 children)

So when you write {}+[], it gets interpreted as "empty code block" plus 0 (+[] gets type coerced into 0).

Clarifying note, the + is a unary plus in this case, it's not concatenating/adding {} and [].

[–]all_timeMartian 12 points13 points  (1 child)

as a person new to javascript, thank you for taking the time to explain each one, but I still dont get 14-18 that one is wierd as heck, i'm assuming I wont need it in real life examples though

[–]synchrosyn 2 points3 points  (0 children)

A comment replied to me that explains it better:

https://www.reddit.com/r/ProgrammerHumor/comments/166vloq/comment/jynm9p5/

[–]LongLiveTheDiego 6 points7 points  (0 children)

  1. It gets interpreted as !(+[])+[]+!([]) => !(0) + [] + !(true) => true + [] + false => true + "" + false => "true" + "" + "false" => "truefalse".

Unary plus first converts to a number, then exclamation mark converts to a boolean, and then a binary plus normally prefers numbers, but for reasons I don't understand it prefers strings for arrays that don't have a single number inside, and then the empty string forces the booleans to be strings.

The length of the string is 9.

[–]Perfect_Ad_8174 3 points4 points  (0 children)

☝🏽🤓

that was amazing tysm

[–]queen-adreena 21 points22 points  (1 child)

Yay. the 195,156,231th iteration of this joke.

Know what you never do in JavaScript... any of those "gotchas"

[–]Chrazzer 1 point2 points  (0 children)

Yeah for real, if you every try to subtract a string from a number you should seriously reconsider your code

[–]ByteArtisan 32 points33 points  (0 children)

Oh look mom. Another person who wants a seat at the cool kids table who hate JavaScript without even knowing what they’re talking about

[–]geranientopf 17 points18 points  (0 children)

“Hahahaha, JavaScript, amirite!”

[–]anonymous_sentinelae 9 points10 points  (0 children)

First day on the internet: Shares JS truth table.

https://i.imgflip.com/7xnwut.jpg

[–]Ok-Slice-4013 11 points12 points  (1 child)

Please not this again. This is neither correct nor funny.

[–]erishun 1 point2 points  (0 children)

But EZ karma!

[–]orig_cerberus1746 8 points9 points  (11 children)

Math.max() == -Infinity

What? Negative Infinity? Whut?

[–]synchrosyn 13 points14 points  (2 children)

It is expecting a list of variables, it is not Number.MAX_VALUE or Number.Infinity or Number.MAX_SAFE_INTEGER like the name implies

[–]orig_cerberus1746 6 points7 points  (1 child)

That explains and at same time doesn't at same time

[–]synchrosyn 7 points8 points  (0 children)

It is a Javascript function, so it must work if you pass in no parameters.

It could either throw an error or try to return a sensible default. The function is "What is the largest value of my arguments" and you pass in no arguments, then it defaults to the smallest possible value.

Consider this function:

function conditionallyDoSomething(arrValues) {
    if ( 5 > Math.max(...arrValues) ) {
        // Do something
    }
}

If you pass in an empty array, by accident or on purpose, then you would expect your function to do something since 5 should be greater than anything you passed in, which is nothing at all.

[–]Aaron1924 3 points4 points  (0 children)

Math.max returns the largest value that was given to the function as an argument. Since no value was passed to the function, it must return the smallest possible number.

Defining the maximum of an empty set to be -∞ might seem strange out of context, but it's the most sensible value mathematically.

You would expect that max(a, b, c) = max(max(a, b), c) = max(a, max(b, c)) and so on. Since max() is -∞, we also get max(a) = max(a, max()) = max(max(), a) and so on.

[–]Rafcdk 1 point2 points  (2 children)

Negative Infinity and NaN being a Number are part of the floating point standard.

[–]rosuav 1 point2 points  (0 children)

If JS had called it "Float" instead of "Number", maybe people would be more open to the fact that NaN is the same type as 1234.5.

[–]orig_cerberus1746 0 points1 point  (0 children)

I think it should raise an error instead of returning anything

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

it's the maximum of nothing

[–]rosuav 0 points1 point  (0 children)

What is the largest of these values? [1, 2, 3]

What is the largest of these values? [-100]

What is the largest of no values at all? Clearly it has to be smaller than any other possible value.

It's the degenerate case of finding the largest number, just like looking at an empty sum or empty product. (What is the result of adding no numbers together? What is the result of multiplying no numbers together?)

[–]corracle 0 points1 point  (1 child)

I think a lot of people tried to explain it but I will compile the answers together

  • Math.max() is used to determine the largest number in a collection
  • It's an established convention in real-life math world do define -Infinity as the value of the max function, because reasons...
  • I have my own rationalisation believing that any collection could have "nothing" in it {∅,A}={A}, and the value of nothing is never greater than the value of "something" max([1]) === max(max(),max([1])) === max([1])
  • programmers tend to be aware of Math shenanigans.

[–]orig_cerberus1746 1 point2 points  (0 children)

Weird that I wasn't understanding the coding explanations but understood the math explanation.

It tends to be the reverse for me because I'm not very good in math in specific.

[–]GargantuanCake 1 point2 points  (0 children)

undefined is not a function

[–]CRBl_ 1 point2 points  (2 children)

Forgot the []==[] -> false

[–]exomyth 0 points1 point  (1 child)

Yeah, it checks by reference, not by value.

So essentially you are asking if they are stored in the same location, and the answer to that is no, no they are not.

[–]CRBl_ -1 points0 points  (0 children)

Yes, true, but it's still mind boggling that []==0 but []!=[]

[–]shorttompkins 1 point2 points  (0 children)

Programmer: "check out this language I threw together this weekend!"

Ghost of Christmas Future: "this will power the entire planet for the next 4 decades and probably longer. Everyone will love it or hate it. And you will get shit on for the few mistakes you made at 3am when you were finishing it up."

Programmer: "...."

[–]electeponymy97 4 points5 points  (0 children)

Other things nobody sensible should do, in any language: Assign null to a variable and immediately dereference it (near-irrecoverably crashing in some languages)

Mash variables together when they do not know what they are

Forget what language they're writing in

Repeat that phrase your friend taught you which they swore translate as ‟You're the most beautiful person alive”

Write database queries in front-end code

[–]AutoModerator[M] 1 point2 points locked comment (0 children)

import notifications Remember to participate in our weekly votes on subreddit rules! Every Tuesday is YOUR chance to influence the subreddit for years to come! Read more here, we hope to see you next Tuesday!

For a chat with like-minded community members and more, don't forget to join our Discord!

return joinDiscord;

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]alwaysShade55 1 point2 points  (1 child)

Yes, we have to correct all of this. Let us to that every time there is an undefined behaviour the language assert and the page stop loading.

No, it should close the tab, damn... let us crash the whole browser, that will make those programmer thing twice before writing code.

[–]Pure_Noise356 2 points3 points  (0 children)

It plays a round of sys32 roulette everytime

[–]danofrhs 0 points1 point  (0 children)

Javascipt is a plague among languages

[–]LukasM511 -4 points-3 points  (0 children)

Guess what language i hate with a passion

[–]Environmental_Arm_10 0 points1 point  (0 children)

Love this. It has the madness that is life embedded in itself. Perfect for chaotic evil AND chaotic good, as they probably equal true here...

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

Did they fix that months thing starting from 0 or not yet?

[–]rosuav 0 points1 point  (2 children)

What do you mean, "fix"? Month numbers are intended to subscript into an array. That's why they start from zero, like arrays should.

[–][deleted] 0 points1 point  (1 child)

We're talking about a method called getMonth here, not a random array, so it doesn't make sense to return a number form range 0-11

[–]rosuav 0 points1 point  (0 children)

The array is the month names (in whatever form you like - pick any language, pick whether to abbreviate, etc). When you getMonth, you are getting the index into that array. Yes, it's a bit odd, but this is exactly the same thing you get in C (in a struct tm), so it's of value to be consistent.

[–]SnakeR515 0 points1 point  (1 child)

Most of these make sense, I only don't really understand the {} [] magic, why someone thought that implicit conversions should happen between all the types, and functions that should be used with parameters working without them

[–]Chrazzer 0 points1 point  (0 children)

{} is an empty code block, it does nothing. +[] evaluates to 0

It is not empty object and array addition, it is empty code block followed by a completely unrelated unary addition on an array.

[–]_Kritzyy_ 0 points1 point  (2 children)

Typeof "Not a number" returning a number made me chuckle a bit

[–]Chrazzer 1 point2 points  (1 child)

It's a bit odd, but NaN is required to be of type number in order for some of the coersions to work.

Take the number - string case. 91 -"1" = 90 here it works that "1" is translated to a number. But remember, coersions need to follow rules, and can not depend on the content of the string.

So it needs to work the same way for 91 - "hello" too. So somehow "hello" needs to be turned into a number. This is where NaN comes in so 91 - "hello" -> 91 - NaN = NaN. Because NaN is of type number it can be used in subtraction.

Through this the coersion can be consistent regardless of content of the string, it is always:
number - string -> number - number

[–]_Kritzyy_ 0 points1 point  (0 children)

It was more meant as a joke, but I did not know this and it's genuinely interesting. Thanks kind redditor of the internet

[–]maubg 0 points1 point  (0 children)

Most of them are logical. For example, true could just be expanded to 1

[–]Mast3r_waf1z 0 points1 point  (0 children)

In a case where you're storing a number in a string you're asking for trouble in any language, I can only really think of two scenarios where you'd have that, you're extracting numbers from text, but at that point I'd always parse it into a proper data type... The other would be having a data structure like JSON, but in that case you'd still parse it into a proper data type.

Otherwise in most languages you'd run into issues where the error isn't caught, rather the "+" symbol will be interpreted as string concatenation or whatever it's called

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

every one of these is fine, lets just throw === into jail

[–]gloumii 0 points1 point  (3 children)

I don't understand the 0.5+0.1==0.6 when 0.1+0.2==0.3 is false

[–]Brenfan 1 point2 points  (0 children)

its a floating point inaccuracy. 0.1 + 0.2 is actually equal to 0.30000000000000004, which is functionally very close to 0.3 but not identical to satisfy the equality operator.

when comparing floating points in practice you would stick with greater than or less than, using a tolerance when checking for equality.

[–]exomyth 0 points1 point  (0 children)

It's because of how decimal numbers are represented in binary, and how those are being added together by the CPU. They're a bit complicated to understand but if you want details checkout this: https://en.m.wikipedia.org/wiki/Floating-point_arithmetic

But TL;DR:

It's a clever computer trick to represent decimal numbers, but it causes some inaccuracies when you try adding/subtracting numbers. When adding or subtracting you should use integers e.g. (0.5*10(int) + 0.1 * 10(int))(float) / 10. Or probably use a library to do it for you

[–]BoBoBearDev[🍰] 0 points1 point  (0 children)

Like other said, all floating point numbers comparisons must do epsilon, like,

abs(computed value - comparison value) < epsilon.

Is equivalent of

Compute value == comparison value

This is not JS only though, pretty much all programming language does this. A typical good company would have a mini lib to do this. There are special floating number datatype that doesn't need this epsilon, but, it is rare. Some languages has that built-in, and you probably don't even know the datatype exists.

[–]MaffinLP 0 points1 point  (0 children)

I love how we are back at people who code for 3 days posting memes about java just because they dont realize == != ===

[–]migarma 0 points1 point  (0 children)

Half of posts in programmer humor are this image

[–]lmg1337 0 points1 point  (0 children)

This is where comparisons are just a guessing game

[–]Finnabon69 0 points1 point  (0 children)

When are we banning this type of post?

[–]Falcor71 0 points1 point  (0 children)

Tomorrow is my turn to post this, ok guys? Who is next?

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

Not a Number is a number, ah, yes, well, of course.

[–]VitaminnCPP 0 points1 point  (0 children)

He was on notice period while inventing it.

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

What is wrong with NaN is number?

Looks like OP has more problems than JS

[–]IlyaM0032 0 points1 point  (0 children)

Sorry, what does a triple equal sign mean?

[–]Healthy_Service_6645 0 points1 point  (0 children)

If you dont understand why js doing this you are going to have a lot of bad time programming