php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #5819 Floating-point precison lost only but always for some "magic" numbers
Submitted: 2000-07-27 17:52 UTC Modified: 2000-07-27 18:22 UTC
From: nightfall at mail dot ru Assigned:
Status: Closed Package: Other
PHP Version: 4.0.1 OS: Win32 (PHP 4.0.1), Linux (PHP 4.
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
34 - 9 = ?
Subscribe to this entry?

 
 [2000-07-27 17:52 UTC] nightfall at mail dot ru
Look at the following sample:

$a=1.16;
$b=intval($a*100)/100;

It's already classic, but... the result is NOT 1.16 again!
Actually $b=1.15

What??! Try multiplying by 1000, and you will get the right one, 1.16
It's funny, how do you think?

This will work with any "magic" number such as 0.29, 0.58, 1.16, 2.32 e t.c., i.e 0.29*(2^n).
I haven't checked all other possible numbers (joke ;-), but it seems to work the same way ANYWHERE.
(At least i can guarantee in PHP 4.0 and 4.0.1 for Win32 and Linux, no matter).

I think, it's related to PHP's internal floating-point engine, but... but... you will see at your own.

-- Helen (nightfall@mail.ru)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2000-07-27 18:07 UTC] stas@php.net
I don't think this is PHP bugs, as the same happens in other languages. You should use floor or round anyway, intval is not a good way to convert IMO. 
 [2000-07-27 18:22 UTC] rasmus@php.net
Not a bug.  You need to understand how computers store floating point values in order to figure this one out.  Basically floating numbers are always approximated.  
For example, if you write out 1/3 in floating point, you can never actually write a perfectly accurate version of that in floating point.  0.333333333333333333...  But when do you stop?  You stop when you have reached the desired precision level.  Now, if you multiply this value by 1000 and then divide by a 1000 you have just multiplied your precision error by 1000.  The floating point value itself won't gain more information to make up for this.
For your example, you set $a to 1.16.  But, in the computer this is actually stored a 1.599999999999999999999999999999999999999 or 1.160000000000000000000000001 because approximations are never exact.  So, to fix you particular problem you would have to add a tiny fuzz factor to make sure your effective rounding will round to 16 if it is within your fuzz factor.  eg.
$fuzz  = 0.000000000001;
$b = (int)($fuzz+($a*100))/100;
(and no, this is not specific to PHP)
 
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Sun Mar 26 08:03:53 2023 UTC