On Mon, 2009-10-12 at 11:08 +0100, Mark Rogers wrote:
Can anyone explain this code's output?
<?php $x = (15/100) * 10.7; $y = 1.605; var_dump($x, $y, round($x,2), round($y,2),round(1.605,2)); ?>
Result: float(1.605) float(1.605) float(1.6) float(1.61) float(1.61)
In other words there is a difference between the values of $x and $y where they should both be 1.605 (and var_dump shows them both to be 1.605).
I assume this is because $x isn't really 1.605, but something very close to (and slightly below) 1.605 due to a rounding issue, so rounding to 2 decimal places causes it to round down not up. But I'm not sure how to change the code to give the correct results?
(15/100 you may notice as VAT; this is a VAT calculation, therefore I'm kinda duty bound to get the right result!)
As you suspect, it's because 15/100 and 10.7 (and 1.605 infact) cannot be exactly represented in IEEE 784 format binary floating point. Thus the calculated value is very slightly below 1.605 and is thus rounded down whereas the constant 1.605 is very slightly above (this is just how the compiler chooses the represent the value of course) and gets rounded up.
Borland had a solution to this problem 25 years ago: they produced a version of Turbo Pascal that worked in binary coded decimal (BCD) instead of base 2, and thus has no problem with decimal representation or calculations. A similar solution is in use today in packages like Sage... perhaps you can find a BCD maths library or compiler switch?
P.