- https://dzone.com/articles/never-use-float-and-double-for-mo... - https://husobee.github.io/money/float/2016/09/23/never-use-f... - https://husobee.github.io/money/float/2016/09/23/never-use-f...
Your balance is $0.30000000004
61–69 of 69 posts
Re: Your balance is $0.30000000004
#62Obligatory reference to the Moonpig billing system, and Mark Dominus' excellent deep-dive article on its design: > Sometimes I see other people fuck up a project over and over, and I say “I could do that better”, and then I get a chance to try, and I discover it was a lot harder than I thought, I realize that those people who tried before are not as stupid as as I believed. That did not happen this time. Moonpig is a…
Re: Your balance is $0.30000000004
#63Re: Your balance is $0.30000000004
#64Earlier quoted context omitted.
> One thing I've always wondered is who the heck is Martin Fowler and why does he have such a following? You don't know the history of your craft; study more, look into where agile came from, the extreme programming movement, and who was involved and how refactoring became a thing. Names like Ward Cunningham, Kent Beck, Martin Fowler, Ron Jeffries, Rob Martin, and Dave Thomas should be familiar to anyone who knows th…
I think I’ve read some of them, but it would be nice to refill my bookshelf with classics. Could you please recommend a re-starter kit of these authors’ top books?
But from the writers:
* Refactoring
* Patterns of Enterprise Application Architecture
* Smalltalk Best Practice Patterns
* Agile Software Development, Principles, Patterns, and Practices
* Domain-Driven Design
* Structure and Interpretation of Computer Programs
* The Pragmatic Programmer
* Design Patterns
* Analysis Patterns
* Implementation Patterns
Fowler is the most prolific writer of the bunch, but he was largely documenting and naming what he saw all of them doing.Re: Your balance is $0.30000000004
#65There are several things that could've prevented this, but apparently they become forgotten every few decades or so. Here's one that could help:
A fixed-point math library using a 64-bit word format like Q1:49:14. That would be a signed, 49-bit whole number with a 14-bit fraction (4 digits for nominal storage / 2 digits for settlement rounded in-place). With a ~$562 trillion limit, it would have an effective range of -562,949,953,421,311.9999 to +562,949,953,421,311.9999. This would work for almost all banking operations but could break down in hyperinflation and the distant future, where reserve and government banking would likely hit "Y2K" issues with it first. Considering 128-bit types exist (although at double the storage cost), it might be worth creating a Q:1:60+:14 format with built-in Hamming code (or similar) ECC for protection beyond that which exists at the hardware level (RAM, possibly CPU caches & IO backplane, probably storage.. but ECC and integrity isn't universal nor always possible).
Re: Your balance is $0.30000000004
#66Earlier quoted context omitted.
This is not a leaky abstraction. JavaScript doesn't pretend that the numeric type is anything other than an IEEE-754 float. It would be a leaky abstraction if JavaScript said "this type can represent all real numbers!" but that would be insanity.
Sure, it's not a leaky abstraction as long as what you want to represent is an IEEE-754 float. Let me know if you ever come across a real-world case where that's exactly what you want. Sure, that's a good-enough abstraction for a lot of cases, which is why a lot of languages implement that standard, and it's pretty reasonable for JS to do that. The pedantic argument you're making is basically that it was never intend…
That's not the case here. JavaScript provides an implementation of 64-bit IEEE-754 floating point numbers. You do not need to know anything about the implementation (is it implemented in hardware? in software? what are the algorithmic details? who cares, they just work!) to use them, they function perfectly like IEEE-754 floating point numbers should.
You're saying "well, some programmers think floating point numbers can represent finite decimal numbers exactly", and that may be true. But it's not JavaScript's fault that some programmers are bad at their jobs and don't understand how floating point numbers work (note that this really has nothing to do with JavaScript: this is true in essentially every programming language). A misunderstanding is not the same as a leaky abstraction.
Think of it like this: no sane person would think the fact that an integral type (i.e. an "int" or a "long" in C/C++/C#/Java/whatever) can't represent the number 3.75 exactly means that "int"'s are a "leaky abstraction". Of course they can't represent 3.75, it's an integral type! Likewise, of course a floating point number can't represent 0.3 exactly: it's a floating point type! They never pretended otherwise! If you want to represent 0.3 exactly, go with a rational or decimal type, that's what they're there for.
> Let me know if you ever come across a real-world case where that's exactly what you want.
All the time! Like, 99% of the calculations you make on a computer, IEEE-754 floats are by far the best choice to represent a number! They're a stupendous numeric type! There's a reason why every CPU and GPU in the world is optimized for floating point operations (that's even how you measure their performance, with mega/tera/peta-FLOPS!), and there's a reason why every language under the sun has built-in support for them! Some languages (like Lua or JavaScript) make them essentially the ONLY built-in numeric type: it's that good!
Re: Your balance is $0.30000000004
#67Earlier quoted context omitted.
The smallest unit of US money is the mill or 1/1000 of a dollar. The smallest unit of US currency is the cent. You're supposed to work in mills and round to cents. Or just work in floats and round as the last step. Or do both selectively depending on which rounding error works in your favor, but don't tell anyone that's what you're doing. The real problem is that nobody at the company seems to have looked at the part…
I really don't see any need or benefit in storing values as mills unless you're writing forex trading platforms. It's inviting more mistakes.
Re: Your balance is $0.30000000004
#68Good example of a leaky abstraction. JavaScript developers almost never have to worry about or completely understand the intricacies of floating-point arithmetic, until errors like this happen. https://en.wikipedia.org/wiki/Leaky_abstraction
I wouldn’t consider this a leaky abstraction. Floating point numbers are explicitly not trying to be an abstraction for real numbers, but rather an approximation for them that is good enough for most purposes (if you’re careful in how you use them). That they might not be taught as such is another problem.
Everyone dealing with JavaScript should be taught about .toFixed(num) for rendering numbers as strings. In fact, anyone working on front end code in any language should learn that language's number formatting tools (e.g. sprintf). There just isn't an excuse for this type of sloppiness.
Re: Your balance is $0.30000000004
#69Earlier quoted context omitted.
Sure, it's not a leaky abstraction as long as what you want to represent is an IEEE-754 float. Let me know if you ever come across a real-world case where that's exactly what you want. Sure, that's a good-enough abstraction for a lot of cases, which is why a lot of languages implement that standard, and it's pretty reasonable for JS to do that. The pedantic argument you're making is basically that it was never intend…
It's not a pedantic argument. A leaky abstraction is a thing when you have some kind of abstraction where the user is supposed to not have to know anything about the implementation details, but where implementation details accidentally "leak" through the abstraction (meaning that the user does, in fact, have to know about the implementation details). That's not the case here. JavaScript provides an implementation of…
You're missing the point: the fact that it's an IEEE-754 floating point number is always an implementation detail. I've literally never been told by a business user, "Hey, I'd like you to add an IEEE float field so we can track some IEEE floats." That doesn't happen.
> Think of it like this: no sane person would think the fact that an integral type (i.e. an "int" or a "long" in C/C++/C#/Java/whatever) can't represent the number 3.75 exactly means that "int"'s are a "leaky abstraction". Of course they can't represent 3.75, it's an integral type!
Sure, nobody will agree with your straw man argument. But de facto people want their float types to not round decimal values to binary values. And even integers are a leaky abstraction--if you expect `int` to represent an arbitrary integer, you're going to be disappointed when the values get large enough. But hey, you're the one who said it was an integral type.
> Likewise, of course a floating point number can't represent 0.3 exactly: it's a floating point type! They never pretended otherwise! If you want to represent 0.3 exactly, go with a rational or decimal type, that's what they're there for.
The difference being that the average developer or business user knows what an integer is, whereas I doubt even you can tell me whether an arbitrary case will go wrong without testing it or doing some back of the napkin math.
> All the time! Like, 99% of the calculations you make on a computer, IEEE-754 floats are by far the best choice to represent a number! They're a stupendous numeric type! There's a reason why every CPU and GPU in the world is optimized for floating point operations (that's even how you measure their performance, with mega/tera/peta-FLOPS!), and there's a reason why every language under the sun has built-in support for them! Some languages (like Lua or JavaScript) make them essentially the ONLY built-in numeric type: it's that good!
Way to not read a full 1/3 of my post. I'll just post it again, please read it this time:
Sure, that's a good-enough abstraction for a lot of cases, which is why a lot of languages implement that standard, and it's pretty reasonable for JS to do that.
I'm not sure why you're leaping to the defense of floats: just because something is a leaky abstraction doesn't mean it's not a useful leaky abstraction. I'm not saying languages or architectures shouldn't implement floats.