Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP rounding problem (5.2.3)?

Tags:

php

rounding

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);
like image 486
Darryl Hein Avatar asked Feb 02 '10 19:02

Darryl Hein


2 Answers

Floats are evil.

Quoting the PHP manual documentation on Floating Point numbers:

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.

If you want to know why and how floats work I recommend watching:
Everything you didn't want to know about JavaScript numbers

like image 81
Bob Fanger Avatar answered Nov 03 '22 01:11

Bob Fanger


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.

like image 31
Ignacio Vazquez-Abrams Avatar answered Nov 03 '22 01:11

Ignacio Vazquez-Abrams