Hacker News new | ask | show | jobs
by vivan 2312 days ago
You would think that this is a fairly rookie error and that big companies would know better, but I regularly see this on Uber: https://i.imgur.com/qDACtG0.png
4 comments

Uber does not use float for money but the internal representation is converted to something displayable in the API layer.

Normally strings are used, for example: https://developer.uber.com/docs/riders/references/api/v1.2/r...

Guess somebody messed up for this case.

Interestingly even in your link you can see that most of the money values (subtotal, total_fare, total_charged) are strings but for some reason total_owed is a float.

Presumably someone messed up but it wasn't caught in code review.

In this case, the value is the "surge_multiplier", which is indeed a float: https://developer.uber.com/docs/riders/references/api/v1.2/e...
On the surface one would think big companies should "know better". I mean, a large company is the accumulation of centuries or even millennia of career experience. Unfortunately, they also contain just as much accumulated nonsense and foolishness; and enough bureaucracy and organizational cruft to hide it forever.
Plus there’s the issue that the career experience isn’t evenly distributed, so you can often have people implementing features without the background necessary to do them right.
A large company is the accumulation of a large number of people, some of who will know better and some of who will not. Hopefully the company is organized such that the people who know will be in a position to catch those kind of errors, but that's not guaranteed.
browser console:

(1.005).toFixed(2)

(1.005).toFixed(20) reveals the problem.

Math.round(1.005 * 100) // wrong

In the end these conversion errors are not solvable in any language, so you have to "cut off" somewhere. There are different approaches to this.

Wasn't there a case where programmers stole the "wrong" cent and wasn't The Office a persiflage on that?

That was the main plot of Office Space.

https://www.imdb.com/title/tt0151804/

According to Snopes, there was a third: Hackers.

https://www.snopes.com/fact-check/the-salami-technique/

Yeah. Underrated movie, actually.
Ah yes, I meant Office Space. Old but great movie.
> In the end these conversion errors are not solvable in any language

Not true at all.

Ruby has BigDecimal: https://ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/Big...

.NET also has a Decimal type.

I've worked on salary calculation applications and e-commerce platforms, and found that language choice makes a big difference.

With insolvable i meant just the technical restrictions of floating point numbers. There are of course solutions. But there is just the fact that binary numbers with discrete length can only be mapped to so many numbers.

If you use numbers directly in exponential form in vanilla javascript, you already get better results.

It's not that they're not solvable, it's just that you have to go out of your way to use the proper type or library. The default floating point type still has problems.
Important caveat: BigDecimal is arbitrary-precision, not infinite-precision. Using it still requires you to think about the precision of each number you operate on.
The story I heard is that the first time this was attempted in real life, the account balance grew so fast that it attracted attention and they were caught.
I've actually seen it on a statement from my bank.