After some experimentation, I realized this. This is a problem with rounding and truncation. Python defaults to rounding ROUND_HALF_EVEN , while PHP just truncates with the specified precision. Python also has a standard precision of 28, while you use 26 in PHP.
In [57]: import decimal In [58]: decimal.getcontext() Out[58]: Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[InvalidOperation, Overflow, DivisionByZero])
If you want Python to mimic the behavior of PHP truncation, we just need to change the rounding property:
In [1]: import decimal In [2]: decimal.getcontext().rounding = decimal.ROUND_DOWN In [3]: decimal.getcontext().prec = 28 In [4]: a = decimal.Decimal('15.80') / decimal.Decimal('483.49870000') In [5]: b = a * decimal.Decimal('483.49870000') In [6]: print(b) 15.79999999999999999999999999
Creating PHP behavior, as with Python by default, is a bit more complicated. We need to create a custom function for division and multiplication that rounds half even, like Python:
function bcdiv_round($first, $second, $scale = 0, $round=PHP_ROUND_HALF_EVEN) { return (string) round(bcdiv($first, $second, $scale+1), $scale, $round); } function bcmul_round($first, $second, $scale = 0, $round=PHP_ROUND_HALF_EVEN) { $rounded = round(bcmul($first, $second, $scale+1), $scale, $round); return (string) bcmul('1.0', $rounded, $scale); }
Here's a demo:
php > $a = bcdiv_round('15.80', '483.49870000', 28); php > $b = bcmul_round($a, '483.49870000', 28); php > var_dump($b); string(5) "15.80"