php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #35896 Round() not doing what it says on the tin
Submitted: 2006-01-04 20:30 UTC Modified: 2006-01-04 22:19 UTC
From: matt at equaliser dot net Assigned:
Status: Not a bug Package: Math related
PHP Version: 4.4.1 OS: Linux
Private report: No CVE-ID: None
 [2006-01-04 20:30 UTC] matt at equaliser dot net
Description:
------------
I know *why* this is happening - so please don't point me to http://www.php.net/manual/en/language.types.float.php - I'm aware of this.

This does not change the fact that a pure call to the round() function using a float value stored in memory can return the wrong result.

The fact that this is easily fixed by rounding to one decimal place further along the float before performing the actual rounding, simply makes the continued existence of this bug more baffling. Why doesn't PHP round() do this internally?

Do all PHP developers need to roll their own round() function if they are going to guarantee mathematical accuracy?


Reproduce code:
---------------
<?php

$input_value = 45;
$vat = $input_value * .175;
echo $vat . '<br />';
echo round($vat , 2) . '<br />';
echo round(strval($vat) , 2) . '<br />';
echo round(round($vat , 3) , 2) . '<br />';

$input_value2 = 7.875;
echo round($input_value2 , 2) . '<br />';

echo round(7.875 , 2) . '<br />';

echo  $vat - $input_value2;

?>


Expected result:
----------------
7.875
7.87
7.88
7.88
7.88
7.88
-8.8817841970013E-16

Actual result:
--------------
7.875
7.88
7.88
7.88
7.88
7.88
-8.8817841970013E-16

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-01-04 20:37 UTC] matt at equaliser dot net
Soory - I got the expected result and the actual result interposed in my previous posting.
 [2006-01-04 20:39 UTC] sniper@php.net
Floating point values have a limited precision. Hence a value might 
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly 
printing it without any mathematical operations.

If you would like to know more about "floats" and what IEEE
754 is read this:
http://docs.sun.com/source/806-3568/ncg_goldberg.html
 
Thank you for your interest in PHP.


 [2006-01-04 22:19 UTC] matt at equaliser dot net
I *KNOW* floating point numbers have limited precision, but surely the round() function *IS* supposed to have absolute precision?

this is not a "BOGUS" bug: float() Still does not do what the documentation says it does.

There's 2 ways of looking at this; either:

1] round() is incorrectly documented, and it should be made clear that the round operation is being performed on a number slightly different that the one apparently represented by the variable.

or:

2] round() should be returning a correctly rounded number which conforms to the string representation of its input variable.

I can roll a very simple fix myself simply by doing one of the following:

round((strval($var) , [precision])
- Take the var out of its float representation, instead using its string representation, then allowing php to convert this string back to a float before rounding.

round(round($var , [precision+1]) , [precision])
- Round the value to [precision+1] before performing the actual rounding, thus removing any fuzziness from the end of the float before actually rounding it.

Both of the above appear to work. What still baffles me is that the PHP manual implies that it has already taken care of this kind of stuff, and is going to return me a rounded version of the input I'm giving it, whereas what it is apparently doing is returning the rounded version of my $vars current representation in the FPU.

for this situation to persist seems wilfully perverse on Zend's part. Surely this should either be fixed, or properly documented?
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Fri Aug 19 08:04:05 2022 UTC