The /
operator returns either a float or an integer. It's interfering with your attempts to use bcadd() correctly. The limitations of floating-point arithmetic will take hold before bcadd() gets a chance to show its stuff.
echo gettype($numerator / $denominator);
double
Use bcdiv()
instead. Note that the bc*() functions take strings as their arguments, and they also return a string.
$ cat code/php/test.php
<?php
$num_1 = 1;
$denom_1 = 1000000000;
# Cast values to string type to be crystal clear about what you're doing.
$q_1 = bcdiv((string)$num_1, (string)$denom_1, strlen($denom_1));
printf("q_1: %s\n", $q_1);
$num_2 = 1;
$denom_2 = 1000000000000000;
# php will do an implicit conversion to string anyway, though.
$q_2 = bcdiv($num_2, $denom_2, strlen($denom_2));
printf("q_2: %s\n", $q_2);
printf("sum: %s\n", bcadd($q_1, $q_2, strlen($denom_2)));
?>
$ php code/php/test.php
q_1: 0.0000000010
q_2: 0.0000000000000010
sum: 0.0000000010000010
Arbitrary-precision arithmetic is inherently slower than floating-point arithmetic. That's the price you pay for dozens, hundreds, or thousands of digits of accuracy.