PHP Adding 2 decimal points numbers (money) gives wrong results in total amount

862

I have an customer invoice table in my MySQL database with a DECIMAL(10,2) field called price.

When fetching these values in php and calculating a sum amount,

ex: in the script

$totalAmount = 0; // initialised them to 

   while(records){              

       $amount = $inv_amount - ($pay_amount + $onamount); //float i guess. 2.22, 14.22
       $totalAmount = $totalAmount + $amount; //float i guess. 2.22, 14.22 ..etc

    }

whenecho $totalAmount; it has a slight error in the final amount 0.01 however when dealing which large datasets around 20,000 this error becomes very considerable such as 200+

what is the safest way to do this when dealing with prices and such with these numbers in PHP? Or will I end up with potential rounding errors and things like that which are common when working with floating point data types?

is using

round 
number_format

is the most suitable solution for this type of a financial application ?

609

Answer

Solution:

Indeed, floating point numbers are not precise.
Either calculate in cent (multiply by 100 and calculate in integers), or calculate in strings using BC Math.

353

Answer

Solution:

Try this:

$totalAmount = number_format($totalAmount, 2, '.', '');
336

Answer

Solution:

If you need accuracy of 2 decimal points:

  1. multiply value by 100
  2. do your operations
  3. divide by 100 and usenumber_format where appropriate
701

Answer

Solution:

have you tried to

round(totalAmount, 2, PHP_ROUND_HALF_ODD);

it should see last decimal number - if it's odd - rounds down, if even - up

927

Answer

Solution:

Well, to begin with, why sum in a php loop when you can do that in mysql? Moreover, just use integer multiplied by 100 and then divide by 100 once you need the final result.

845

Answer

Solution:

You could usenumber_format

Ex:(for two decimal points)

$number = 12345.5667;
echo $result = number_format($number, 2);

Or you could useround function in MySql:

ROUND(number,2)
861

Answer

Solution:

I recommend doing calculations on SQL Level with queries or views.

Firstly, using 64 bit integers on PHP is risky because; on overflow, it switches to float and you lose precision. When it's money, the problem is more serious. You should acually calculate a column with sql and just get the value from there. Money is a long type and it will often convert to float on php and your people will lose or win some cents depending on the mood of php engine. You can't work with decimal type on php, even if you multiply by 100 and keep it as an integer, long numbers with overflow will be converted to float automatically. Calculate your values on MYSQL if you want to use decimal numbers or convert your field into int.

If your server has an 32 bit cpu, the WORD length is 32 bit so integers in php engine are 32 bit integers. This makes the likelihood of overflow higher. On an 64 bit system, you can work more comfortably.

Using a round function on a money value is ridiculous and unprofessional in this case. Don't do it.

Reading this document will help you a lot.

php documentation of integers says

Integer overflow

If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.

Calculation on SQL level will ensure precision for money type. Getting the money type to php will result in a float value, and you can multiply it by 100 and divide by 100 later BUT it increases the rish of overflow again because php will use an 32 bit float number for storage. If you are using 32 bit float why is the data field decimal? So it's inconsistent if you do that. an 32 bit number i already not so big, and an 32 bit float loses some of its capacity on floating point, so it's more likely to reach over capacity when you multiply by 100.

USE SQL

People are also looking for solutions to the problem: php - NicEdit upload on your own server

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.