BCMath

Arbitrary Precision with BCMath and BcMath\Number

The bcmath extension does exact decimal arithmetic on numeric strings of any size. Its functions (bcadd(), bcsub(), bcmul(), bcdiv(), bcmod(), bcpow(), bcsqrt(), bccomp()) take an explicit $scale and truncate beyond it. PHP 8.4 added bcround(), bcfloor(), bcceil(), bcdivmod() and the immutable BcMath\Number class, with overloaded operators and automatic scale.

BCMath functions and a VAT calculation with BcMath\Number (bcmath.php)PHP
<?php
use BcMath\Number;
echo bcadd('0.1', '0.2', 1), ' ', bcmul('123456789012345678901234567890', '3'), ' ',
    bcdiv('1', '3', 20), ' ', bcround('2.345', 2), "\n";     // strings, explicit scale
$price = new Number('19.99');                                 // PHP 8.4 object API
$net   = $price * 3;
$vat   = ($net * '0.2')->round(2, RoundingMode::HalfEven);
$gross = $net + $vat;
printf("net %s (scale %d) + VAT %s = %s | %s %s | %s\n", $net, $net->scale, $vat, $gross,
    var_export($gross > 70, true), $gross->compare('71.96'), new Number('1') / 3);
set_error_handler(fn(int $no, string $msg) => print "E_DEPRECATED ($no): $msg\n");
echo $price + 0.1, "\n";                                      // a float operand becomes int 0
Output
0.3 370370367037037036703703703670 0.33333333333333333333 2.35
net 59.97 (scale 2) + VAT 11.99 = 71.96 | true 0 | 0.3333333333
E_DEPRECATED (8192): Implicit conversion from float 0.1 to int loses precision
19.99

Multiplication adds the operands' scales; division uses the dividend's scale plus 10, so pass a scale to div() for more. The trap: a float operand is cast to int, so + 0.1 adds zero, with only an E_DEPRECATED notice that Ubuntu 225 's default error_reporting hides. Build values from strings, and use compare(), since === tests identity. MySQL 524 DECIMAL values arrive through PDO as strings (Special Column Types), ready for new Number(). For big integers gmp is faster; for currencies, see brick/money 1,928 (https://github.com/brick/money 1,928 ).