tags:

views:

300

answers:

3

I'm wondering if I found an issue with the rounding in PHP, specifically 5.2.3 (I'm not sure about other versions at the moment):

$t = 0;

$taxAmount = (5.000 / 100) * 0.7;
$t += $taxAmount;

var_dump($t); // float(0.035)
var_dump(round($t, 2)); // float(0.03)
var_dump(number_format($t, 2)); // string(4) "0.03"

To me 0.035 should round to 0.04 or am I just crazy?

Edit

Thxs to NebyGemini's answer, I figured I would do this instead:

$t = 0;

$taxAmount = bcmul(bcdiv(5.000, 100, 3), 0.7, 3);
$t += $taxAmount;

var_dump($t); // float(0.035)
var_dump(round($t, 2)); // float(0.04)
var_dump(number_format($t, 2)); // string(4) "0.04"

Which works perfect.

BTW, I'm calculating a tax in a shopping cart. The order total is the 0.70 (70 cents) and the tax is 5%.

Edit

Thxs to Ignacio Vazquez-Abrams's answer, this is to show where the problem lies:

printf('%.18F', 5.000 / 100 * 0.7);
+3  A: 

Python says:

>>> repr(5./100*0.7)
'0.034999999999999996'

This is due to IEEE754 accuracy limitations. Use a fixed-point type if you need exact accuracy.

Ignacio Vazquez-Abrams
Any idea if there's a way to get this in PHP?
Darryl Hein
`printf('%.18F', 5.000 / 100 * 0.7);`
Ignacio Vazquez-Abrams
A: 

You can use PHP_ROUND_HALF_UP, but there's a issue that number self transform to "99999..."

Flávio Toribio
+3  A: 

Floats are evil.

Quote from http://php.net/float

"So never trust floating number results to the last digit, and never compare floating point numbers for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available."

Bob Fanger
Thanks, ended up using the bc math functions.
Darryl Hein