Handling Floating-Point Precision in PHP: Common Issues and Solutions with bcmath
This article explains PHP floating-point precision issues, demonstrates common arithmetic errors, and shows how to use the bcmath extension and various rounding functions such as floor, ceil, round, and number_format to achieve accurate numeric calculations in backend development.
Introduction
PHP floating-point numbers have limited precision, which can cause noticeable errors in financial, e‑commerce, and other applications. PHP typically uses the IEEE‑754 double‑precision format, giving a maximum relative error of 1.11e-16, and non‑basic operations may produce larger errors. Never trust a floating-point result to be exact or compare two floating-point numbers for equality; use arbitrary‑precision functions or the gmp extension when higher accuracy is required.
1. Operations
Incorrect (using native floating‑point)
<code>// addition
$a = 0.1; $b = 0.7; $c = intval(($a + $b) * 10); echo $c."<br>"; // output: 7
// subtraction
$a = 100; $b = 99.98; $c = $a - $b; echo $c."<br>"; // output: 0.019999999999996
// multiplication
$a = 0.58; $b = 100; $c = intval($a * $b); echo $c."<br>"; // output: 57
// division
$a = 0.7; $b = 0.1; $c = intval($a / $b); echo $c."<br>"; // output: 6</code>Correct (using bcmath )
<code>// addition
$a = 0.1; $b = 0.7; $c = intval(bcadd($a, $b, 1) * 10); echo $c."<br>"; // output: 8
// subtraction
$a = 100; $b = 99.98; $c = bcsub($a, $b, 2); echo $c."<br>"; // output: 0.02
// multiplication
$a = 0.58; $b = 100; $c = intval(bcmul($a, $b)); echo $c."<br>"; // output: 58
// division
$a = 0.7; $b = 0.1; $c = intval(bcdiv($a, $b)); echo $c."<br>"; // output: 7</code>The bcmath extension also provides functions such as bccomp (compare), bcmod (modulus), bcpow (power), bcpowmod (power with modulus), bcscale (set default scale), and bcsqrt (square root).
2. Common Numeric Handling Methods
Floor (round down)
<code>echo floor(5.1); // output: 5
echo floor(8.8); // output: 8</code>Ceil (round up)
<code>echo ceil(5.1); // output: 6
echo ceil(8.8); // output: 9</code>Standard rounding
<code>echo round(5.1); // output: 5
echo round(8.8); // output: 9
// round to two decimal places
echo round(5.123, 2); // output: 5.12
echo round(8.888, 2); // output: 8.89
// truncate without rounding
echo substr(round(5.12345, 3), 0, -1); // output: 5.12
echo substr(round(8.88888, 3), 0, -1); // output: 8.88</code>Banker's rounding
Rules: When the digit after the rounding position is 5, look at subsequent digits; if any are non‑zero, round up. If the trailing digits are all zero, round to the nearest even digit (banker's rounding). Example:
<code>1.2849 = 1.28 // round down
1.2866 = 1.29 // round up
1.2851 = 1.29 // round up because digits after 5 are non‑zero
1.2850 = 1.28 // round down because preceding digit (8) is even
1.2750 = 1.28 // round up because preceding digit (7) is odd</code>Number formatting (thousands separator)
<code>echo number_format('10000.98', 2, '.', ','); // output: 10,000.98
echo number_format('340888999', 2, '.', ','); // output: 340,888,999.00</code>php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.