I can't explain the underlying "magic" with the bits, but I'm pretty sure this is related to how fixed and float numbers are represented and cast.
A few things to note in your code:
- the vars
$div
and $random
are int
and stay int
- in you
if
you are comparing an int
to a float
with !=
so the values are casted before comparing them
While researching the answer I also came across this SO post, which shows that var_dump
is secretly rounding the numbers
This is my version of your code, I wanted to try multiple approaches:
for($i=0; $i<100; $i++) {
$original = mt_rand(100, 1000);
$div = mt_rand(1,100);
$internal_part = $original / $div;
$internal = $internal_part * $div;
$bcmath_part = bcdiv($original, $div, 50);
$bcmath = bcmul($bcmath_part, $div, 50);
$diff_1 = $original - $internal;
$diff_2 = bcsub($original, $bcmath, 50);
var_dump($original, $internal, $div);
echo "<p>Full scale results:</p>";
echo sprintf("Internal: %s <br>", rtrim(number_format($internal, 100),0));
echo sprintf("Bcmath: %s <br>", rtrim(number_format($bcmath, 100),0));
echo "<p>both as Float</p>";
echo sprintf("Division: <code>%f</code> ", $internal_part);
echo sprintf("Internal: <code>%f</code> != <code>%f</code> Diff1: %f<br>", (float)$original, $internal, $diff_1);
echo sprintf("Division: <code>%f</code> ", $bcmath_part);
echo sprintf("Bcmath: <code>%f</code> != <code>%f</code> Diff2: %f <br>", (float)$original, $bcmath, $diff_2);
echo "<p>both as INT</p>";
echo sprintf("Internal: <code>%d</code> != <code>%d</code><br>", $original, (int)$internal);
echo sprintf("Bcmath: <code>%d</code> != <code>%d</code>", $original, (int)$bcmath);
echo "<hr>";
}
In the "Full scale" print, you should see that the internal division (default) results are just very-very close to an integer, but they aren't:
Just one example of 740 / 43 * 43:
Simple division and multiplication : 739.9999999999998863131622783839702606201171875
using Bcmath: 740
I think var_dump
just gives up after a number of nines and calls it an integer, while the actual value is still a float.
Conclusion: use bcmath or something precise in these cases - especially in finance