php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #36008 incorrect round() & number_format() result
Submitted: 2006-01-14 05:15 UTC Modified: 2010-11-05 18:37 UTC
Votes:19
Avg. Score:4.0 ± 1.6
Reproduced:14 of 18 (77.8%)
Same Version:5 (35.7%)
Same OS:10 (71.4%)
From: adi at rogers dot com Assigned:
Status: No Feedback Package: Math related
PHP Version: 5CVS-2006-06-14 OS: win32 only
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: adi at rogers dot com
New email:
PHP Version: OS:

 

 [2006-01-14 05:15 UTC] adi at rogers dot com
Description:
------------
Very lame/unreliable ;)
Both round() and number_format() succumb to this problem.
They cannot handle float or double variables properly even though those variable types are "flawed / limited" as apparently described numerous times on here by PHP personnel. Well my code below appears to showcase the bug which will hopefully not be shot off as "bogus" like many times before as reported in the past by various people.

I found a work-around which I will now be using. Convert your value to a string variable before passing it to the round() or number_format() function.

Reproduce code:
---------------
$num=12.5*1.15;    // Produces 14.375 as type: double.
$num_same_thing=14.375; // Produces 14.375 as type: double.
echo "Wrong: ".round($num, 2)."\r\n";
echo "Wrong: ".number_format($num, 2)."\r\n";
echo "'Magically' correct: ".round($num_same_thing, 2)."\r\n";
echo "'Magically' correct: ".number_format($num_same_thing, 2)."\r\n";
// The above two variables are the same value and same type, yet are rounded differently.
settype($num, "string");
// Now that $num is a string, we get the right result.
echo "Converted to string and is now correct: ".round($num, 2)."\r\n";
echo "Converted to string and is now correct: ".number_format($num, 2)."\r\n";

Expected result:
----------------
The functions should have outputted 14.38 no matter how the variables of type 'double' were assigned the value 14.375.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-01-14 11:16 UTC] sniper@php.net
Output on my machine using default precision 12:
Wrong: 14.38
Wrong: 14.38
'Magically' correct: 14.38
'Magically' correct: 14.38
Converted to string and is now correct: 14.38
Converted to string and is now correct: 14.38

And it works exactly like it's supposed to.
round() rounds up to 2 decimals. Same goes for number_format(). 

14.375 == 14.38 but 14.374 == 14.37

There is no bug here, and please, don't bother reopening this yet again.
 [2006-01-14 15:55 UTC] adi at rogers dot com
I just confirmed this issue to still exist on the following systems:

Windows XP Pro SP2 [IIS 5.1 ISAPI] (PHP 5.1.2 / php.ini precision: 12)
Windows XP Pro SP2 [IIS 5.1 CGI] (PHP 5.1.0RC1 / php.ini precision: 12)
Windows Server 2003 Enterprise x64 Edition SP1 [IIS 6.0 CGI] (PHP 5.1.2 / php.ini precision: 12)

PHP was installed on all three systems manually (not using the installer).

Hope that helps in isolating this issue.
 [2006-01-14 16:06 UTC] sniper@php.net
What EXACTLY is the output when you set precision to 32?

 [2006-01-15 06:34 UTC] adi at rogers dot com
As requested, the exact output with 32 as the precision:

Wrong: 14.369999999999999
Wrong: 14.37
'Magically' correct: 14.380000000000001
'Magically' correct: 14.38
Converted to string and is now correct: 14.369999999999999
Converted to string and is now correct: 14.37
 [2006-01-15 06:40 UTC] adi at rogers dot com
Oh, and as I had suspected, here is the value of $num with 32 precision: 14.374999999999998
With 12 as the precision, it is: 14.375
 [2006-06-14 15:50 UTC] iliaa@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2006-06-14 22:11 UTC] adi at rogers dot com
Regretfully, the same output:

5.2.0-dev

Wrong: 14.37
Wrong: 14.37
'Magically' correct: 14.38
'Magically' correct: 14.38
Converted to string and is now correct: 14.38
Converted to string and is now correct: 14.38


The 32 precision results are also the same [as the ones on January 15].
 [2006-10-10 07:45 UTC] troy20 at mail dot ru
Code:
for ($i = 1.075;$i <= 1.975;$i=$i+0.1)
	{echo round($i,2);}
Result:
1.08, 1.18, 1.28, 1.38....
But if
 	echo round(1.275,2);
	echo round(1.275*100);
we have 1.27 and 127. 

Another "same" example:
for ($i = 1.075;$i <= 20.975;$i=$i+0.1)
	{echo round($i,2);}

Win2003 + Apache 2.0.59 + php 5.1.6
 [2006-10-10 21:44 UTC] adi at rogers dot com
Amen to that ;)
 [2006-10-30 13:30 UTC] dave at koales dot co dot uk
I think this is a Windows vs others thing.  I have the same rounding error using PHP 5.0.5 on Windows XP SP2.

The same problem does not exist on my webhost, who use PHP 4.3.9 and Redhat Linux (need any more detail).

The code I used was:

echo "Correct VAT = " . round( 0.525, 2 ) . "\r\n";
echo "Wrong VAT = " .  round( 3 * ( 17.5 / 100.0 ), 2 ) . "\r\n";

Outputs 0.53 for each on webhost (under Linux) and 0.52 for the second test under Windows (0.53 for the first test).

I've also had very bizarre rounding errors with MySQL.  The rounding error came and went depending on how the calculation was constructed!
 [2006-10-31 00:39 UTC] adi at rogers dot com
Aww well it's too late for me to bug it for Windows Vista as we've entered Release Candidate 2 :(  I'll test this again on IIS7 with the final version of Vista...
 [2007-01-07 04:07 UTC] iliaa@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2007-01-09 02:56 UTC] terrychangsharp at gmail dot com
I tested the code on PC + FreeBSD 6.1 + Apache 2.2.3 + PHP 5.2.0 and get the same results. Actually, the seemingly coincident numbers $num and $num_same_thing are in fact not the same thing: $num - $num_same_thing yields -1.7763568394003E-015, not zero, so $num is smaller than 14.375 and round($num) is 14.37, not 14.38. Thus this "bug" is more like a floating point error thing, not a real bug.
 [2007-01-15 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2007-03-16 15:36 UTC] me at nospam dot com
I don't have a simpler test case, but in doing more testing, I found that the rounding apparently just doesn't work. When you print out a number that was rounded, it will appear correctly, but when you try to do math functions with other similar numbers (ie 6.08 - 6.08), I will get a remainder of like 2.039283e-16. However, setting the type to each variable as a string made it work correctly.
 [2010-11-05 18:18 UTC] rinseout at gmail dot com
Similar problem on Vista home premium, PHP 5.2.5:

<?php
$numbers = array(0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009);
foreach ($numbers as $number)
  print $number."->".number_format($number, 2, '.', ',')."<br>";
?>

0.001->0.00
0.002->0.00
0.003->0.00
0.004->0.00
0.005->0.01
0.006->0.01
0.007->0.01
0.008->0.01
0.009->0.01

as expected... however...

<?php
$numbers = array(78.221,78.222,78.223,78.224,78.225,78.226,78.227,78.228,78.229);
foreach ($numbers as $number)
    print $number."->".number_format($number, 2, '.', ',')."<br>";

?>

78.221->78.22
78.222->78.22
78.223->78.22
78.224->78.22
78.225->78.22
78.226->78.23
78.227->78.23
78.228->78.23
78.229->78.23

?
78.225->78.22
?

no fiddling with the precision parameter enabled me to fix this.
 [2010-11-05 18:37 UTC] rasmus@php.net
PHP 5.2.5?  Upgrade!
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 19:01:28 2024 UTC