0

I'm currently doing some simple addition of decimal numbers in PHP (currency), but for some reason I can add the same numbers twice and get different results.

What I'm doing is getting some rows from a MySQL table in PHP, adding the total for each receipt and storing the result in another MySQL table as decimal(10,2):

 <?php   
foreach($query_result as $row) {
     $total_receipts = $total_receipts + $row['total'];

     //my locale requires commas as decimal separators and points for thousands:
     echo number_format($total_receipts,2,",",".");
     }
  ?>

The strange thing is I can do the same operation twice on the exact same rows and get two different results, with regard to the decimal point. For example, when I add the following numbers:

3621.94
1230.29
1025.00
1025.00

The first time the correct value of 6902.23 was inserted in the DB. When I ran it the second time, the value inserted in the DB was 6.90. For some reason, the second time around it decided to move the decimal point.

I'm not using number_format() to insert in to the DB , I'm storing $total_receipts without modifications.

In this particular example the error appeared in the second try, but sometimes it can show up the first time and the second time be correct.Sometimes I cannot even replicate the bug.

What am I doing wrong? I've been reading about bcmath, but I'm not sure if I should be using it for this simple addition.

RafaelM
  • 159
  • 4
  • 13
  • 1
    Have you check if you get the same kind of issue when hardcoding values into variables or only when reading from db? – developerwjk Mar 17 '15 at 23:17
  • possible duplicate of [PHP Adding 2 decimal points numbers (money) gives wrong results in total amount](http://stackoverflow.com/questions/11114861/php-adding-2-decimal-points-numbers-money-gives-wrong-results-in-total-amount) – Till Helge Mar 17 '15 at 23:23
  • 2
    Rule #1 when working with currencies: NEVER, EVER store or elaborate currency units as floats/decimals! ALWAYS use integers, representing in cents (e.g. $2.12 = 212 cents and store the integer). That not only will solve you pains because of float operations, but you won't have problems with locales, etc – ItalyPaleAle Mar 17 '15 at 23:28
  • @developerwjk I tried replicating it 4 times with hardcoded values and couldn't. I'll keep testing. – RafaelM Mar 18 '15 at 00:53
  • @Qualcuno The original values I'm reading from MySQL come from a CSV file that has these type of values: 1762.229 . That should be 1762.23, but if I multiply by 100 I would get 176222.9 . How can I deal with that? – RafaelM Mar 18 '15 at 00:57
  • @RafaelM then just convert them to integers *before* storing them into MySQL. You can do a string operation for that (you read the string from CSV, split() where the dot is and then concat the two numbers as strings before casting to int) – ItalyPaleAle Mar 18 '15 at 01:03
  • I just realized I could probably use MySQL instead to do the adding? As in using sum in to add all $row['total'] and assing it to $total_receipts or would I still face the same issues with floating point arithmetic? – RafaelM Mar 18 '15 at 01:15
  • @RafaelM if you do arithmetic with floats, you'll end up having issues with floating point arithmetics. Again, just convert the dollars to cents when you read from the CSV file (it's as easy as a simple string operation) and store cents in MySQL. – ItalyPaleAle Mar 18 '15 at 13:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73272/discussion-between-rafaelm-and-qualcuno). – RafaelM Mar 18 '15 at 16:48

1 Answers1

0

Please use number_format() to insert into DB:

<?php
$total_receipts = 0; //Always initialize vars
foreach($query_result as $row) {
    $total_receipts += $row['total'];

    //this way to insert into DB
    echo number_format($total_receipts, 2, ".", "");
}
?>
José Carlos PHP
  • 1,417
  • 1
  • 13
  • 20