Home  >  Article  >  Backend Development  >  Is PHP's `precision` Workaround Reliable for Precise 2-Digit Money Calculations?

Is PHP's `precision` Workaround Reliable for Precise 2-Digit Money Calculations?

Linda Hamilton
Linda HamiltonOriginal
2024-11-07 06:39:02541browse

Is PHP's `precision` Workaround Reliable for Precise 2-Digit Money Calculations?

Can I Rely on PHP PHP.INI Precision Workaround for Floating Point Issue?

Introduction

Floating-point arithmetic involves representing fractional numbers as binary fractions, which may not have exact representations. This can lead to rounding errors.

Question 1:

Can this workaround ensure precise 2-digit calculations for money?

Answer 1:

No. PHP precision settings cannot guarantee precise 2-digit calculations, as precision can be increased during calculations.

Question 2:

Example of when the workaround fails:

ini_set('precision', 8);
$a = 5.88; // cost of 1kg
$q = 2.49; // User buys 2.49 kg
$b = $a * 0.01; // 10% Discount only on first kg
echo ($a * $q) - $b; // result: 14.5824 (not precise for money calculations)

Question 3:

Which php.ini.precision value suits best for 2-digit money calculations?

Answer 3:

PHP precision is not a recommended metric for precise financial calculations.

Simple Test

Using bcmath, number_format, and subtraction:

$a = 342349.23;
$b = 341765.07;

ini_set('precision', 20);
echo $a - $b, PHP_EOL; // 584.15999999997438863
echo floatval(round($a - $b, 2)), PHP_EOL; // 584.15999999999996817 (rounding issue)
echo number_format($a - $b, 2), PHP_EOL; // 584.16
echo bcsub($a, $b, 2), PHP_EOL; // 584.15 (precision set to 20)

ini_set('precision', 14);
echo $a - $b, PHP_EOL; // 584.15999999997
echo floatval(round($a - $b, 2)), PHP_EOL; // 584.16
echo number_format($a - $b, 2), PHP_EOL; // 584.16
echo bcsub($a, $b, 2), PHP_EOL; // 584.16 (precision set to 14)

ini_set('precision', 6);
echo $a - $b, PHP_EOL; // 584.16
echo floatval(round($a - $b, 2)), PHP_EOL; // 584.16
echo number_format($a - $b, 2), PHP_EOL; // 584.16
echo bcsub($a, $b, 2), PHP_EOL; // 584.00 (precision set to 6)

ini_set('precision', 3);
echo $a - $b, PHP_EOL; // 584
echo floatval(round($a - $b, 2)), PHP_EOL; // 584
echo number_format($a - $b, 2), PHP_EOL; // 584.16
echo bcsub($a, $b, 2), PHP_EOL; // 0.00 (precision set to 3)

Conclusion

Using number_format for money calculations is recommended for consistency. Storing in cents is also an option.

Update

Question 1: Will precision workaround fail for numbers between 0..999999.99?

Answer 1:

Yes, due to the large number of combinations, a full test is impractical.

Example:

$a = 0.19;
$b = 0.16;
...
$h = $a + $b + ...; // Total value: 0.4

$i = $h - $a - $b - ...; // Result: 1.0408341E-17 (expected: 0.00)

Question 2: How to estimate when precision workaround fails?

Answer 2:

Mathematical solutions exist, but it's not within the scope of this discussion.

The above is the detailed content of Is PHP's `precision` Workaround Reliable for Precise 2-Digit Money Calculations?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn