Live data from Hacker News

Using floating-point numbers for money

evanjones.ca

61–70 of 128 posts

Re: Using floating-point numbers for money

#61
post #37

I ran into a weird problem this week trying to convert a string "8.95" to an integer (8.95) that made me question if even Int is good enough and as suggested in the comments here, use BigInt or equivalent for anything to do with numbers. This also happens with Javascript and Elixir, not just Ruby. So perhaps it has something to do with how the cpu stores the numbers? I know this isn't StackOverflow, but could someone…

This is pretty standard for IEEE-754 floats/doubles. Try entering 8.95 into Float Toy [0]. It's about 1 * 2^3 * 1.11875. If you look at the red part, you see there's a "repeating decimal" 00011(1100)(1100).. that gets truncated, just like I can "recognize" 0.33 as "one-third" but if you want to multiply it by 10 I'll (probably) give you 3.30, and it's no longer special. There is always a lossy "compression" when you move across co-prime bases (pretty sure) and truncate the repeating decimals.

What's really hard is printing a floating-point number. Since you have to print "8.95" when all you really have is a base-2 rational very close to it, you want to be sure you don't actually need to print 8.94999998. If you miss the last couple bits in the red part in Float Toy, you'll see the print algorithm shifts away from the 8.95 answer.

[0] https://evanw.github.io/float-toy/

Re: Using floating-point numbers for money

#62
I think this is kind of funny. Using floats and rounding at some fixed precision before rounding to penny precision is basically exactly the same as using integer multiples of whatever you're first rounding the float to. So you're basically not using floating point anymore, you're just using a float type to represent fixed point integers. The problem as I see it here is that you need to be careful to round to the fixed precision at the right places. The easiest way to not miss a place is to do it after every operation, and the best way to do that is to abstract your money type as a class. So now what we're comparing is a fixed point class holding a float vs an int. In my opinion, holding an int is the better option, because it's slightly more obvious when the values overflow the maximum range of that integer than when the precision of the float drops below your fixed point rounding delta. In either case you need to add some error handling and I also prefer branching on ints than floats (mostly because of a big perf difference on the CPU I used to work on).

Re: Using floating-point numbers for money

#63
post #5

Sorry, but I remain skeptical. The same people who use `float` for financial calculations are probably the same people who don't understand how/why to do the rounding described to avoid these problems. Way too many programmers think that they are working in base 10 when using float. Why not just make them use it, and keep them out of trouble. Also, I wonder what the overhead of rounding every operation is? Comparable…

> I wonder what the overhead of rounding every operation is? Comparable to the cost of using a proper Decimal class?

For what it’s worth, for the major ICs (Intel, NVIDIA, etc.) there is zero extra overhead. A choice of rounding modes is part of the floating point operation’s instruction. And keep in mind that a floating point op is always rounding no matter what you do, the question is whether it’s always using the same rounding strategy consistently, whether you can control it, and whether it has what you need.

> I remain skeptical

You are correct.

There are good reasons not to use float for money that the article didn’t discuss, and perhaps the author isn’t aware of. You run out of integer precision at 2^24, which is only 16 million. If you process a 20 million dollar payment in units of dollars, you might be off by at least a dollar. That error will multiply with every floating point op done on the result. If your units are pennies, the largest safe value is only 160,000 dollars. If you ever subtract floats, like say make a payment or withdrawal, you can run into catastrophic cancellation without knowing it. Deposit $200k and then withdraw $199k, suddenly you have a small balance with large error that could remain in your account and continue to grow until the balance is zero. https://pharr.org/matt/blog/2019/11/03/difference-of-floats....

Re: Using floating-point numbers for money

#64
Disagree with this one - problem is that floating point errors tend to be cumulative and doing something simple like summing a year of sales records the errors start to reflect in pennies surprising quickly. But luckily this has been a solved problem for decades - fixed point and binary coded decimal.

https://en.m.wikipedia.org/wiki/Fixed-point_arithmetic

https://en.m.wikipedia.org/wiki/Binary-coded_decimal

Re: Using floating-point numbers for money

#65
Floating point numbers are numbers in scientific notation for computers. I don't see people without computers doing finance calculations in scientific notation. It's not natural and error happens because of this.

Floating point numbers were not created to represent numbers which could be non-integers. They were created to represent numbers in scientific notation. Very useful for physics and scientific calculations, but not in finance domains.

Re: Using floating-point numbers for money

#66
post #5

Sorry, but I remain skeptical. The same people who use `float` for financial calculations are probably the same people who don't understand how/why to do the rounding described to avoid these problems. Way too many programmers think that they are working in base 10 when using float. Why not just make them use it, and keep them out of trouble. Also, I wonder what the overhead of rounding every operation is? Comparable…

> I would argue that financial math by definition needs to be accurate to the penny. Where is "pretty close" financial calculations considered acceptable? There is a difference between analysis and accounting. There are many financial models (e.g. Black-Scholes-Merton option pricing) that are analytic in nature and use transcendental functions, so the idea of getting an exact, arbitrary-precision answer is hopeless.…

This is an excellent point.

When computing around money, you're either working with magnitudes or units.

If you don't know which, you're working with units; use a Decimal.

Re: Using floating-point numbers for money

#67
post #39

A lot of financial firms use an integer of the smallest indivisible unit of currency wherever possible (stripe is one). This has the handy property that string and numeric representations are identical so no risk of being flipped into scientific notation by some layer. That happens more often than you’d think. FX is a different world. Spot FX trading systems are fully automated and compute rates to 5 DP. That was 15…

For shits and giggles: $ python3 Python 3.7.4 (default, Sep 7 2019, 18:27:02) [Clang 10.0.1 (clang-1001.0.46.4)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> print (0.1 + 0.1 + 0.1) 0.30000000000000004 $ irb 2.5.1 :001 > print 0.1 + 0.1 + 0.1 0.30000000000000004 => nil Chrome browser console: > 0.1 + 0.1 + 0.1

Is this because PHP is correct, or is it because PHP rounds reprs at a different level of precision?

Re: Using floating-point numbers for money

#68
> A 64-bit floating-point number can represent 15 decimal digits, which is all balances less than 10 trillion (9 999 999 999 999.99), with two digits after the decimal place

There are real monetary quantities for which this is insufficient. The GDP of Indonesia is measured in 10s of quadrillions of Rupiah. In cases of hyperinflation this kind of overflow can happen even for human-level accounting.

Use real fixed point decimal math.

Re: Using floating-point numbers for money

#69
post #51
post #45

Earlier quoted context omitted.

Yes, but why switch systems though ?

How are you going to do linear interpolation, let alone exponential growth, without floating-point? On August 1 you made $1000, on August 7 you made $1100, assuming that growth is linear, how much are you going to make on August 20? If you have some routines for dividing fixed-point numbers, one, why do you believe they have more accuracy than floating point (especially if you're doing divisions by numbers that aren'…

> How are you going to do linear interpolation, let alone exponential growth, without floating-point?

Fixed point is one answer, but I see you know that already. I don’t know what the banks use for interest, but I can guarantee that it’s not float32.

> If you have some routines for dividing fixed-point numbers, one, why do you believe they have more accuracy than floating point

Fixed point routines do not have more best-case accuracy than float, given the same number of bits ... but float32 definitely has a worst-case accuracy that is very very bad compared to a fixed point number.

> why do you believe they’re more correct than floating point?

Can’t speak for the GP, but I think asking about correctness is a straw man. The issue is really about safety, predictability, and controllability. Floating point can be very accurate, but guaranteeing that accuracy is notoriously difficult, and it depends very much on the unknown ranges of your intermediate calculations. Fixed point, on the other hand, never changes accuracy as you go, so you don’t get surprises.

Re: Using floating-point numbers for money

#70
No, please don't. Often you have to combine money with quantities that also need unit of measure conversions and this just is one step too far. Frankly, chasing the error goes from a programming problem to a contract problem very quickly.

Also, you are going to end up storing in decimal fields in the database anyway.

Post reply on HN