Live data from Hacker News

Using floating-point numbers for money

evanjones.ca

41–50 of 128 posts

Re: Using floating-point numbers for money

#41
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…

The problem here isn’t integers at all, as 8.95 is not an integer but an integer (8) plus a fraction (0.95 or 95/100==19/20). That’s in decimal, but since computers use binary, your decimal fraction must be converted to a binary fraction. This is what floating point is used for, although it’s important to know that floating point is an approximation of the real number line, and also that fractions that are rational in decimal may be irrational in binary, namely if the decimal denominator is not a power of two.

Looks like that’s what’s going on with your example. Floating point approximation of an otherwise unrepresentable irrational binary which resulted in that repeating sequence when converted back to decimal again. I don’t know how BigDecimal works but I guess just by the name it is not floating point but rationals represented by arbitrary precision integer numerators and denominators.

Definitely read up on how floating point representation works, with binary mantissas and exponents, normalization, and converting decimal fractions to binary fractions.

Re: Using floating-point numbers for money

#42
post #22

Earlier quoted context omitted.

How would you suggest to store and calculate things like taxes? For example in NYC the retail sales tax is 8.735%. Obviously the final amount could be stored as an integer in cents, but I'm talking about the tax rate and the calculations of it. I guess you need to calculate the tax for each item, round it to cents (and I assume the rules on how you round can vary by jurisdiction, so it's not just calling your languag…

> Obviously the final amount could be stored as an integer in cents, but I'm talking about the tax rate and the calculations of it. The tax rate (like most things associated with money) should be stored as an exact decimal (fixed point decimal, decimal floating point, or arbitrary precision decimal all work.) > I guess you need to calculate the tax for each item, round it to cents (and I assume the rules on how you r…

To be fair, there are a range of little issues when applying tax rates, not connected to the representation of the numbers involved.

In Italy the generic VAT rate is 22%.

When you expose a price (to the final customer) it is always included VAT, but VAT needs to be explicited on fiscal documents (receipt and/or invoices).

So you have an article priced to the public Euro 2,69 (included 22% VAT), what is the net price and how much is the VAT? 2,69/1,22=2,204918...

So, let's try rounding it to 2,20: 2,20x0,22=0,484=0,48 no, wait, 2,20+0,48=2,68

Ok, let's try rounding it to 2,21: 2,21x0,22=0,4862=0,49 no, wait, 2,21+0,49=2,70

You have to use the first and add 0,01 to the VAT to have it work:

2,20+(0,48+0,01)= 2,69

Re: Using floating-point numbers for money

#43

Why do so many languages not have a decimal type as a primitive value? Is it legacy? Is it because a decimal type must fundamentally be an object that wraps some other primitive values?

Looks like Go v2 might get decimal floating point numbers support: https://github.com/golang/go/issues/19787

Re: Using floating-point numbers for money

#44
post #23

The funny thing is that if you're dealing with (US Treasury) bonds, (EDIT: binary) floats are actually kind-of the right thing, since they trade in 32nds of a dollar (and binary fractions thereof)[1][2] > Unlike U.S. equity markets, which switched to decimal pricing in 2001, U.S. Treasury securities still trade in fractions. In particular, prices are quoted in 32nds of a point, where a point equals one percent of par…

Unfortunately it's 32nds of a 100th, so they still don't work in floats (because floats are stored normalised, as 1.x in binary). Eg. 117.125

Is it? The NY Fed site says it's 32nds of a dollar:

> • Prices are quoted in 32nds of a dollar.

> [...] Note and bond prices are quoted in dollars and fractions of a dollar. By market convention, the normal fraction used for Treasury security prices is 1/32.

Re: Using floating-point numbers for money

#45
post #40
post #24

Earlier quoted context omitted.

> I would argue that financial math by definition needs to be accurate to the penny. Yes, indeed. There is no such thing as "financial math that does not need to be accurate to the penny". I wonder if OP has ever worked with a bookkeeper...

Bookkeeping needs to be accurate to the penny. Estimating growth for the next quarter or last years GDP doesn't.

Yes, but why switch systems though ?

Re: Using floating-point numbers for money

#47
post #23

Earlier quoted context omitted.

Unfortunately it's 32nds of a 100th, so they still don't work in floats (because floats are stored normalised, as 1.x in binary). Eg. 117.125

Is it? The NY Fed site says it's 32nds of a dollar: > • Prices are quoted in 32nds of a dollar. > [...] Note and bond prices are quoted in dollars and fractions of a dollar. By market convention, the normal fraction used for Treasury security prices is 1/32.

Right, but the price is about 100, not 1.

If you had a price of 1.25 then you could represent this as a float as (binary) 1.01. However if you have 117.25 then that's (decimal) 1.83203125 * 2^-6. You can see how you quickly run out of bits.

Re: Using floating-point numbers for money

#48

Why do so many languages not have a decimal type as a primitive value? Is it legacy? Is it because a decimal type must fundamentally be an object that wraps some other primitive values?

Postgresql has an accurate decimal type that can handle any size or precision. Slower than Float or Integer but works fine in practice.

Re: Using floating-point numbers for money

#49
post #22
post #3

Of course you can , but for the vast majority of cases, you shouldn’t . Floating points aren’t designed to solve the problems financial calculations bring, they’re designed for general purpose math and efficiency. If you’re programming a point-of-sale system, or a ecommerce site or something, using IEEE-754 floats would be madness. The increase in performance compared to decimal types is absolutely infinitesimal, and…

How would you suggest to store and calculate things like taxes? For example in NYC the retail sales tax is 8.735%. Obviously the final amount could be stored as an integer in cents, but I'm talking about the tax rate and the calculations of it. I guess you need to calculate the tax for each item, round it to cents (and I assume the rules on how you round can vary by jurisdiction, so it's not just calling your languag…

Easy, either implement a decimal type (4 fractional digits) as most programming languages have them implemented by users. or multiply by 10000 then do your calculation and then divide by 10000 again. I used a decimal type for the administration program I coded.

Re: Using floating-point numbers for money

#50
post #49
post #22

Earlier quoted context omitted.

How would you suggest to store and calculate things like taxes? For example in NYC the retail sales tax is 8.735%. Obviously the final amount could be stored as an integer in cents, but I'm talking about the tax rate and the calculations of it. I guess you need to calculate the tax for each item, round it to cents (and I assume the rules on how you round can vary by jurisdiction, so it's not just calling your languag…

Easy, either implement a decimal type (4 fractional digits) as most programming languages have them implemented by users. or multiply by 10000 then do your calculation and then divide by 10000 again. I used a decimal type for the administration program I coded.

> Easy, either implement a decimal type

Great, how do you become confident that your hand-rolled decimal type is less buggy than the known hazards of using floating-point?

Post reply on HN