Integers, Floats and Precision

Scalar Types and Their Limits introduced the 64-bit int, which overflows silently into a float, and the IEEE 754 double, with about 15 significant digits. Above 2^53 a double skips integers, and decimal fractions such as 0.1 have no exact binary form.

Stored float values, tolerant comparison and integer division (floats.php)PHP
<?php
$sum = 0.1 + 0.2;
echo $sum, ' | ', json_encode($sum), ' | ', sprintf('%.20f', 0.1), ' | ',
    json_encode((float) (2 ** 53 + 1)), "\n";        // 2^53 + 1 has no exact double
function nearlyEqual(float $a, float $b, float $rel = 1e-9): bool
{
    return abs($a - $b) <= $rel * max(abs($a), abs($b), 1.0);
}
echo json_encode([nearlyEqual($sum, 0.3), floor((0.1 + 0.7) * 10), (int) (19.99 * 100),
    (int) round(19.99 * 100), is_nan(sqrt(-1)), NAN == NAN]), "\n";
$cents = 10_000;                                      // 100.00 split three ways, in cents
[$share, $left] = [intdiv($cents, 3), $cents % 3];
echo "$share x 3 + $left | ", intdiv(-7, 2), ' ', -7 % 2, ' ', fmod(-7.5, 2), ' ',
    fdiv(-7, 0), "\n";
Output
0.3 | 0.30000000000000004 | 0.10000000000000000555 | 9007199254740992
[true,7,1998,1999,true,false]
3333 x 3 + 1 | -3 -1 -1.5 -INF

echo follows precision (14 digits) and shows 0.3; var_dump() and json_encode() follow serialize_precision (-1, the shortest round-trip form) and show the truth. (0.1 + 0.7) * 10 is 7.999..., and 19.99 * 100 is 1998.999..., so round() before floor() or an (int) cast, and compare floats with a tolerance. For money, count integer cents or use BCMath (BCMath), and store DECIMAL, never FLOAT (DECIMAL vs FLOAT). intdiv() truncates toward zero and % takes the left operand's sign; giving the remainder cent to the first share splits 100.00 into 33.34 + 33.33 + 33.33. fdiv() returns INF where / and % throw (Arithmetic and Strings).