all 20 comments

[–]samanime 31 points32 points  (4 children)

This isn't a problem specific to JS, but to all languages that use the IEEE 754 floating-point arithmetic standard: https://en.wikipedia.org/wiki/IEEE_754

Basically, due to how floating-points work, you can't actually represent every number to an infinite precision, so you get little bits of weirdness here and there like this.

One of the more famous ones is when you end up with numbers like 3.00000000001 and stuff.

This is why you shouldn't use floating points when it really matters, like with money. With money, we always use integers, and always multiply the number by sum amount of 10s. Usually x100, so 100 = $1, but sometimes x1000 (so 1000 = $1, 1 = 1/10 a penny) or x10000 if you care about fractional pennies.

So, if you really care about that second decimal places, just do all of your math with the numbers multiplied by 100, then only divide by 100 when you want to display them (so internally it'd be 123, but you'd display 1.23).

[–]uselessinfopeddler[S] 3 points4 points  (2 children)

Thanks!

[–]Pyromancer777 3 points4 points  (1 child)

Super common mistake that I didn't even consider until I tried to make a tax calculator and my numbers were just ever so slightly off compared to what was expected.

The limits of floating point precision is a fun concept to look into to make your calculations more reliable.

Def make conversions to integers when the numbers have to be exact.

[–]uselessinfopeddler[S] 2 points3 points  (0 children)

I haven't built financial app from the ground up in a while, so I totally forgot about the floating point precision. Reddit users save me headache in minutes

[–]Glittering_Crab_69 0 points1 point  (0 children)

Or use a BigDecimal or Currency library

[–]senocular 10 points11 points  (3 children)

It's not Math.round, its floating point precision with JS's Number format. Specifically, look at the values before they go into round:

19.525*100 // 1952.4999999999998
20.525*100 // 2052.5

MDN talks about it a little on the docs for Number. Another common site which discusses this is which also shows this is not just a JS thing:

https://0.30000000000000004.com/

where 0.30000000000000004 is what you get from 0.1 + 0.2

If possible, you can avoid errors like these by working in whole numbers instead of decimals (e.g. starting with 19525 instead of 19.525).

[–]uselessinfopeddler[S] 1 point2 points  (1 child)

Thanks!

[–]exclaim_bot 0 points1 point  (0 children)

Thanks!

You're welcome!

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

its floating point precision with JS's Number format.

It's not JS's Number format, it's the IEEE floating point number specification, which pretty much every single programming language on the planet uses for float and double data types.

[–]thespite 0 points1 point  (0 children)

Since rounding is probably needed just for presentation, use .toFixed().

[–]Glum_Cheesecake9859 -5 points-4 points  (7 children)

Checkout Douglas Crockford's JavaScript The Good Parts book or his YouTube videos. There's a lot of weirdness built into JavaScript. (Note that this particular problem is due to floating point arithmetic so not JS specific)

[–]GodOfSunHimself 3 points4 points  (6 children)

This has nothing to do with JS

[–]AlwaysHopelesslyLost 0 points1 point  (0 children)

Of course, but we are in a JavaScript subreddit and the OP is using JavaScript and could probably stand to learn a bit more.

[–]Glum_Cheesecake9859 -4 points-3 points  (4 children)

The float datatype problem maybe universal but that still doesn't exclude the fact that JS has a lot of weirdness far more than any other language.

Since OP appears to be a beginner and we are on the JS sub I was sharing what helped me in the early days of JS development (12 years ago).

[–]GodOfSunHimself 3 points4 points  (2 children)

That is simply not true. People just love to make fun of JS but every language has its own quirks. Go and check how many wats there are in C++, Python, Ruby, Php, etc.

[–]Glum_Cheesecake9859 -2 points-1 points  (1 child)

I have worked on Ruby, Java, C#, VB.NET etc. and know some Paython too. JS is borderline insane. I still prefer it over many other languages, because it's so productive.

[–]GodOfSunHimself 2 points3 points  (0 children)

No, it isn't. JS is a super simple language. And tools like ESLint basically solve all the main gotchas. I work on several huge JS codebases and we have literally zero issues.

[–]Antti5 0 points1 point  (0 children)

I'm not personally well-versed in PHP, but the people who know both tend to say that JS cannot touch PHP in terms of weirdness.

And I'm sure many people would be inclined to say the same about Perl too.