Shabbyrobe
Shabbyrobe

Reputation: 12628

How do I safely perform money related calculations in PHP?

I'm working on a few report output scripts that need to do some rudimentary calculations on some money values.

I am aware of the limitations of floating point arithmetic for this purpose, however the input values are all in a decimal format, so if I use the arithmetic operators on them PHP will cast them to floats.

So what is the best way to handle the numbers? Should I use BCMath? Is there something akin to Decimal in .NET? Or is it safe to use the arithmetic operators if I cast back to int?

Upvotes: 14

Views: 7763

Answers (4)

Mirrow43
Mirrow43

Reputation: 1

Use BCMath or GMP for precise arithmetic on monetary values. Converting to integers (e.g., working in cents) is also safe for basic calculations, but BCMath is preferable for flexibility and readability.

Upvotes: -1

cjs
cjs

Reputation: 27261

If you're working with reasonable amounts (to a "normal person"), using floating point is not likely to be a problem, especially if you're just adding and subtracting amounts, rather than doing, say, interest calculations.

If you're looking for a quick fix, switching to integer is not likely to help you; you still have to deal with overflow. (Someone edited here to mention that if PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. But then you're back to your original problem of using floating point!) Arbitrary length integers (GMP, referenced from that page) can help.)

Basically, doing this in a half-assed way works in most cases, and is cheap; doing it correctly is a serious pain. My suggestion is to look at this as a business problem: if someone complains about missing a cent, give them a dollar, and don't bother starting on a real solution until you're going to save more dollars by doing that.

Upvotes: -4

nickf
nickf

Reputation: 546253

Don't work in Dollars ($1.54), work in cents: (154c). Unless you need to be performing tasks where fractions of a cent are important, then you'll be working with integers and all is well. If you are interested in tenths of a cent, then just multiply everything by ten!

Upvotes: 13

Robert K
Robert K

Reputation: 30328

If you use BCMath all values will be stored in strings and passed to the functions as strings, just as the result will be a string. So, you needn't do any casting but ensure that the number given to the function is a value numeric value. Personally, if the math requires a high amount of precision on the decimal side then use BCMath.

Upvotes: 14

Related Questions