this post was submitted on 26 Jul 2025
1 points (100.0% liked)

Software Gore

1308 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
 
top 25 comments
sorted by: hot top controversial new old
[–] aeronmelon@lemmy.world 0 points 9 months ago (2 children)

Technically correct, that is beneath the total.

[–] Zachariah@lemmy.world 0 points 9 months ago

No, it totally dominates the total.

[–] finitebanjo@lemmy.world 0 points 9 months ago

If the Subtotal is -7e43 and the Total is 283.96 doesn't that mean anon's flight cost 7e43 + 283.96? Honestly, one hell of a discount.

[–] scrubbles@poptalk.scrubbles.tech 0 points 9 months ago* (last edited 9 months ago) (2 children)

Finance developers know the hell that is money and precision. I've worked fintech for years and god, so many gotchas.

I got a tech screen for a company that was brilliant. The question was "take these transactions (from a file) and add them to a database.

To any decent engineer they would see that and say "sure thing! Easy let's do it!"

To me, a senior fintech engineer though I was like "oh dear God, let's see if we can even get a quarter of this done"

(For those who have not gone through the trial by fire that is handling money in professional code, you've been warned, I'll leave just the few off the top of my head in spoilers below.)

gotchas from that problem

  • What currency are the transactions in?
  • are all of the transactions in the same currency?
  • will I need to support currencies with other precision's? (3, 4, 0 decimal places? More?)
  • do we accept transactions that are not precise to their currency? (If they say $4 is that valid? Or is that an error because they should have sent $4.00)
  • what currencies do we accept? Can we accept every currency, or do we have a list of acceptable currencies?
  • if we accept multiple currencies do we accept the money into an account or do we need to exchange it?
  • how do I validate that the transaction accounts are valid?
  • what if one transaction is invalid? Do we still accept the rest of the file? Should we reject the entire file in case their system is wrong?
  • which parser are we using? Is it precise? (Most parsers parse through float or double to get into the language, and are not precise)

Money is not easy friends

[–] FizzyOrange@programming.dev 0 points 9 months ago (2 children)

Honestly none of those "gotchas" sound at all surprising to me. A currency enum and f64 for the amount will cover 99.99999% of use cases. u64.u64 fixed point if you really need it (you probably don't).

Try dates/times. That's serious pain.

[–] scrubbles@poptalk.scrubbles.tech 0 points 9 months ago* (last edited 9 months ago) (2 children)

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.

[–] FizzyOrange@programming.dev 0 points 9 months ago (2 children)

A f64 is a double, floating point precision type, aka not precise

f64 is perfectly precise.

The correct format to store money in? A string

Lol ok.

$3.99999999898998888181

If only we had this thing called rounding...

[–] scrubbles@poptalk.scrubbles.tech 0 points 9 months ago (1 children)

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 as 01000010001000000000101000111101 in a float type, which is literally stored as 40.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"

[–] funkless_eck@sh.itjust.works 0 points 9 months ago (1 children)

re your last point: or just watch Superman III.

[–] scrubbles@poptalk.scrubbles.tech 0 points 9 months ago

or office space!

[–] I_am_10_squirrels@beehaw.org 0 points 9 months ago

Have you seen office space?

[–] Revan343@lemmy.ca 0 points 9 months ago (1 children)

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)

Lol, that feels exactly like writing 'four (4)' in a sentence, I love it

[–] scrubbles@poptalk.scrubbles.tech 0 points 9 months ago

It feels weird at first, but it really is the best safest way to store the auditable amount, and really most of the time with currency you don't need to ever mutate it at the DB level, so why introduce the possibility at all of a precision error. One thing that is common is that you do a order by of your transactions, which is why the imprecise is useful, but then you display the string version to the user. It also keeps the precision rather than truncating the precision off (with money the .00 is important, most banks require exact precision to know that you didn't accidentally have a rounding/truncation error)

[–] GissaMittJobb@lemmy.ml 0 points 9 months ago (1 children)

A currency enum and f64

You failed entirely and should not be handling money in code

[–] FizzyOrange@programming.dev 0 points 9 months ago (1 children)

Why? It sounds like you are under the common and false impression that you can't use f64 for money.

[–] GissaMittJobb@lemmy.ml 0 points 9 months ago (1 children)

You can't use it if you ever want to do any operations on said money, due to the loss of prescision.

Enums are not a good idea for the currencies either.

[–] FizzyOrange@programming.dev 0 points 9 months ago* (last edited 9 months ago) (1 children)

Yes you can. You're vastly underestimating the size of an f64. Give me a concrete example of a money operation that fails with f64 (for normal companies; assuming you aren't a stock exchange or Visa or whatever).

Enums are not a good idea for the currencies either.

Why not?

[–] GissaMittJobb@lemmy.ml 0 points 9 months ago (1 children)

Yes you can. You're vastly underestimating the size of an f64. Give me a concrete example of a money operation that fails with f64 (for normal companies; assuming you aren't a stock exchange or Visa or whatever).

0.1f64 + 0.2f64 != 0.3f64

Why not?

Encoding in assumptions about a fixed amount of supported currencies in a system is broadly speaking not a good idea

[–] FizzyOrange@programming.dev 0 points 9 months ago

0.1f64 + 0.2f64 != 0.3f64

It does if you round it to the nearest penny.

Encoding in assumptions about a fixed amount of supported currencies in a system is broadly speaking not a good idea

Most sensible programming languages allow enums to be non-exhaustive.

[–] Rozz@lemmy.sdf.org 0 points 9 months ago

As a UX designer I totally believe all of that. I've seen that in other industries.

[–] xia@lemmy.sdf.org 0 points 9 months ago (2 children)

Repeat after me: "Don't use floating-point numbers for currency values."

[–] swab148@lemmy.dbzer0.com 0 points 9 months ago (1 children)

I still wanna see someone get naneinf money in Balatro

[–] SuperSpruce@lemmy.zip 0 points 9 months ago

With the cryptid mod you probably can

[–] hperrin@lemmy.ca 0 points 9 months ago

Instead, use arrays.

int[] total = […itemsPriceArrays.flatten()];
[–] Etterra@discuss.online 0 points 9 months ago

Remember to take your payout in the form of cash.