Patabugen
Patabugen

Reputation: 317

How do I round inprecise floating point addition in PHP?

When adding floats I'm getting consistent inconsistencies. I'm aware that floats are not accurate - but how do I add 1.95 to 1.95 and end up with 3.9 instead of 3.89999999? Rounding does not work. number_format can fix the final result but not during the addition.

$amountPaid = 0;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";
$amountPaid = $amountPaid + 1.95;
var_export($amountPaid); echo "<br>\n";

echo '<h1>Rounding does not work</h1>';
var_export(round($amountPaid,1)); echo "<br>\n";

This is the output:

0
1.95
3.8999999999999999
5.8499999999999996
7.7999999999999998
9.75
11.699999999999999
Rounding does not work
11.699999999999999

I've also tried rounding at every step, using number_format (but that returns a string) and using the $amountPaid += syntax.

Upvotes: 1

Views: 81

Answers (1)

Philipp
Philipp

Reputation: 15629

Your problem is var_export

Looks like since version 5.4.22 var_export uses the serialize_precision ini setting, rather than the precision one used for normal output of floating-point numbers. As a consequence since version 5.4.22 for example var_export(1.1) will output 1.1000000000000001 (17 is default precision value) and not 1.1 as before.

http://php.net/manual/de/function.var-export.php#113770

In addition to that I should mention, that the serialize_precision setting changed to -1 in PHP 7.1 and your code works just fine.

So instead of using var_export, just use echo for printing the value or var_dump to dump the value.

In most cases your code will just work fine, if you do your calculations and just round the value if you print it. If you need a bigger accuracy, you should work with big number libraries like bc math. They aren't as fast as IEEE numbers, but don't have rounding problems like this.

Upvotes: 4

Related Questions