this post was submitted on 26 Jul 2025
139 points (97.9% liked)
Software Gore
1181 readers
1 users here now
A community for posting software malfunctions
Deliberately bad software or bad design is not software gore, it must be something unintentional
Icon base by Delapouite under CC BY 3.0 with modifications to add a gradient and shear it
founded 2 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
Wow uh, nope. A f64 is a double, floating point precision type, aka not precise. You should never store currency values in that, otherwise you, well you just recreated the exact bug we see in the image above.
Bud, like I said, the problem comes off as "lol it's so easy", but unless you have literally worked with money before - real actual dollars and cents, it is much more complex than you give it credit for.
Your approach may appear fine, it may look fine, but with money precision matters. Floating points are not precise, they are an exponential representation of a function that will give you a pretty good estimation of the value you want - but they are not precise. In money, you must be precise. You fuck up that value, you get customers calling in, you get banks rejecting your transfers, you get governments closing you down because your code is shit and they don't trust you to manage people's money.
Now, I'm not a jerk, I'll tell you the correct answer, we should all learn. The correct format to store money in? A string. Immutable, perfectly precise to whatever precision you want, and whatever the customer types in is exactly what you can store. You parse that string to make sure it's valid, you use your currency enum as you said (which I wouldn't btw, currencies actually change more often than you would expect), to make sure it passes to a correct numerical value that fits within the bounds of that currency. If you need to mutate that value, in the same language you go to a precise type, mutate, and then return it back as a string value. Storing in a database then you store the value as string, and best practice is to store the "imprecise" amount next to it as whatever the database supports. That way, you have the auditable real value ($4.00) stored for use on reports and taxes, and the imprecise ($3.99999999898998888181) that you can use for sorting, filtering, and regular database options.
Strings also should be used over the wire, aka in json payloads in rest apis. This is because JavaScript and other languages parse the number types as floats, which again are imprecise. String is the only safe way to translate money between languages and data stores.
For Rust, as I assume that's what you're referring to, you should use something like rust_decimal - crates.io: Rust Package Registry https://crates.io/crates/rust_decimal a precision based crate for handling money.
f64
is perfectly precise.Lol ok.
If only we had this thing called rounding...
Double is not perfectly precise. It is quite literally a function that calculates what the value should be. There are converters to show the drift: https://www.h-schmidt.net/FloatConverter/IEEE754.html
$40.01
is literally stored as01000010001000000000101000111101
in a float type, which is literally stored as40.009998321533203125
. The margin of error goes up the larger the number.Either you're just trolling, or incredibly arrogant. I have been coding in the FinTech space for over a decade and can tell you firsthand that these are real issues, and have real consequences.
But hey, don't take my word for it:
There have been some famous disasters thanks to floating point math
As for rounding, I can't even think of a way to describe what a terrible idea that is. I'd suggest reading those articles and asking the stock exchange why they don't "just round it" when dealing with millions of transactions that deal with fractions of pennies. "Just round it"
re your last point: or just watch Superman III.
or office space!