views:

86

answers:

3

I need to add, multiply and compare currency values in PHP and need to be sure that it is exact down to a single cent.

One way is to store everything in float, use round before and after each operation and mind machine epsilon when comparing for equality. Quite cumbersome imho.

Another way is to store the whole thing as cents in integer data types, plus remember to convert back and forth anytime I work with the database (mysql, where I use the decimal data type). Inelegant, and many error pitfalls, imho.

Another way is to invent my own "datatype", store all values in strings ("34.12") and create my own mathematical replacement functions. These function would convert the value to integers internally, do the calculation and output the result again a strings. Suprisingly complicated, imho.

My question: what is the best practice for working with currency values in PHP? Thanks!

+3  A: 

You should always work with integers.
Store the values as ints in your database, use ints to do calculations and when, and only when, you want to print it, convert it to some readable format.

This way you completeley circumvent floating point problems, which, generally, is a big problem when working with money ;)

Edit: One thing worth mentioning: You need to think about precision before you start working this way. As others have pointed out, you might need to work with values smaller than a cent, so you need to do your multiplication/division accordingly. (ie currency * 1000 for a .001 precision)

Dennis Haarbrink
MySQL and others have the DECIMAL / NUMERIC format which is designed specifically to circumvent floating point problems and give exact results.
Tatu Ulmanen
I assumed irony, so I didn't vote you down. Please confirm I was right :)
thomasmalt
@Tatu Ulmanen: Sure, Mysql does. But if you then go about and do something like equality testing in php, you might get unexpected results.
Dennis Haarbrink
+1 assuming you are not working with values smaller than 1ct. Just use integers in both the database and php and convert when displaying like Dennis is suggesting.
captaintokyo
+2  A: 

As of MySQL v5.0.3, MySQL stored the DECIMAL datatype not as a floating point variable so you don't need to worry about precision errors.

To correctly manipulate precision numbers in PHP use it's arbitrary precision math functions.

Store as decimal values, as currency is intended to be stored, you can get units of money smaller than cents. You only need to round the values when displaying the figures, not during manipulation, which isn't cumbersome at all imho.

Andrew Dunn
I'm sorry but I don't understand you. There is no decimal data type in php. If you meant float: you cannot reliably test for equality using them.
CruftyCraft
PHP has a set of functions designed specifically for the manipulation and comparison of precision numbers: http://www.php.net/manual/en/ref.bc.php
Andrew Dunn
+1  A: 

Keep the values as cents and use integers. Write classes or helper functions to encapsulate displaying in the UI and handling values in your database queries. If you use float, there is too much risk you'll lose a cent somewhere.

MattSmith