Live data from Hacker News

Using floating-point numbers for money

evanjones.ca

51–60 of 128 posts

Re: Using floating-point numbers for money

#51
post #45
post #40

Earlier quoted context omitted.

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 ?

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't divisible by 10, as in the example above - don't you have the same problem as with floating point?), and why do you believe they're more correct than floating point? Did you write a test suite? Do you know what needs to be tested? What prevented you from writing the test suite for the floating-point calculations you were originally doing to do?

Re: Using floating-point numbers for money

#53
> Solution: Round after every operation

No, the solution is not to use floating point numbers to store money.

I worked on an iOS app in fintech for years, and let me assure you, using floating point numbers to calculate currency is an exercise in frustration and lack of correctness. When balances are wrong you're losing your customers money, which in turn loses trust in your product. You know it's inexact, an approximation, and your customers want an exact answer.

Just do it with a fixed-precision decimal number, and represent it as a string.

Re: Using floating-point numbers for money

#54

Earlier quoted context omitted.

> No, do not do financial calculations in floating point. Floating point is fine, so long as it is big enough for the application and decimal (not binary) floating point. Fixed point decimal is easier to get right, and, really, arbitrary precision decimal (or, for even more generality, arbitrary precision rational) is even easier to get right.

Updated my comment, thanks. I meant binary float. Decimal float is rather unknown (unfortunately), so most people imply binary when they say "float", and most languages don't even have decimal float, so the warning is necessary. PSA: If your favorite language doesn't support ieee754 decimal float, start badgering them to add it! This has gone on long enough, and the inertia against change is strong.

> If your favorite language doesn't support ieee754 decimal float, start badgering them to add it! This has gone on long enough, and the inertia against change is strong.

Without hardware support (which makes decimal float a good choice for performance), I'm not sure I've ever run into a use case where decimal float is a compelling choice if I already have arbitrary precision decimal and hardware-backed binary float types available.

Re: Using floating-point numbers for money

#55

> Solution: Round after every operation No, the solution is not to use floating point numbers to store money. I worked on an iOS app in fintech for years, and let me assure you, using floating point numbers to calculate currency is an exercise in frustration and lack of correctness. When balances are wrong you're losing your customers money, which in turn loses trust in your product. You know it's inexact, an approxi…

[deleted]

Re: Using floating-point numbers for money

#56
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 (4 fractional digits) as most programming languages have them implemented by users.

C#, Ruby, Python, and Java, at least, among industrially popular languages all provide a fixed and/or arbitrary precision decimal type in either the core language or stdlib. Lower level languages sometimes don't, and JavaScript, among higher-level popular languages, notably does not.

Re: Using floating-point numbers for money

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

In some countries, cents are a very insignificant number(they have the additional three zeros for whole numbers) and businesses are allow to round to the nearest hundredth, most small to medium businesses round to an integer.

Re: Using floating-point numbers for money

#58
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 i…

> That’s in decimal, but since computers use binary

Well, if you tell them to, e.g., by using a binary floating point type instead of a decimal type.

Re: Using floating-point numbers for money

#59
You might get unexpectedly negative financial results if you don't use floored division and modulo properly:

https://stackoverflow.com/questions/4467539/javascript-modul...

>JavaScript % (modulo) gives a negative result for negative numbers

>Question: According to Google Calculator (-13) % 64 is 51. According to Javascript (see this JSBin) it is -13. How do I fix this?

>Solution: ((i % n) + n) % n

The Forth-83 standard word /MOD (or FM/MOD) implemented floored division properly, subtly breaking many old FORTH programs, but it was a step (or rather a truncation) in the right direction, towards negative infinity instead of zero.

https://www.nimblemachines.com/symmetric-division-considered...

>Symmetric division considered harmful

>Since its 1983 standard (Forth-83), Forth has implemented floored division as standard. Interestingly, almost all processor architectures natively implement symmetric division.

>What is the difference between the two types? In floored division, the quotient is truncated toward minus infinity (remember, this is integer division we’re talking about). In symmetric division, the quotient is truncated toward zero, which means that depending on the sign of the dividend, the quotient can be truncated in different directions. This is the source of its evil.

https://forth-standard.org/standard/core/FMDivMOD

>Rationale:

>By introducing the requirement for "floored" division, Forth 83 produced much controversy and concern on the part of those who preferred the more common practice followed in other languages of implementing division according to the behavior of the host CPU, which is most often symmetric (rounded toward zero). In attempting to find a compromise position, this standard provides primitives for both common varieties, floored and symmetric (see SM/REM). FM/MOD is the floored version.

>The committee considered providing two complete sets of explicitly named division operators, and declined to do so on the grounds that this would unduly enlarge and complicate the standard. Instead, implementors may define the normal division words in terms of either FM/MOD or SM/REM providing they document their choice. People wishing to have explicitly named sets of operators are encouraged to do so. FM/MOD may be used, for example, to define:

    : /_MOD ( n1 n2 -- n3 n4) >R S>D R> FM/MOD ;

    : /_ ( n1 n2 -- n3) /_MOD SWAP DROP ;

    : _MOD ( n1 n2 -- n3) /_MOD DROP ;

    : */_MOD ( n1 n2 n3 -- n4 n5) >R M* R> FM/MOD ;

    : */_ ( n1 n2 n3 -- n4 ) */_MOD SWAP DROP ;

Re: Using floating-point numbers for money

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

> I know this isn't StackOverflow, but could someone shed some light on to what's happening here? https://ideone.com/1U7rgf

You cannot store 8.95 in a binary float (independent of precision). It is basically the same problem that you cannot store 1/3 as a decimal number.

Post reply on HN