php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49715 float to string conversions
Submitted: 2009-09-29 20:52 UTC Modified: 2009-10-01 19:53 UTC
From: terrafrost at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.2.11 OS: Windows XP
Private report: No CVE-ID: None
 [2009-09-29 20:52 UTC] terrafrost at gmail dot com
Description:
------------
Displaying a float in base-10 when fractional values are involved is difficult, as per <http://php.net/float>.  Even if fractional values aren't involved, displaying the float might still be problematic, if the number you're trying to display is to big to be stored in the mantissa of a floating point number.

Problem is, floating point numbers aren't always displayed correctly, even if the mantissa can hold the number in question.  For example, if you have a double precision floating point number, your mantissa has 53 bits.  The following corroborates this:

<?php

$test = 1;
$bits = 0;
while (fmod($test, 2) == 1) {
    $test = 2 * $test + 1;
    $bits++;
}

echo $bits;
?>

That, for me, displays 53.

The problem occurs with anything utilizing 48 or more mantissa bits:

<?php
$bits = 0;
while (true) {
    if (bcpow(2, $bits) != (string) pow(2, $bits)) {
        break;
    }
    $bits++;
}
echo $bits;
?>

Reproduce code:
---------------
<?php
echo pow(2, 52);
echo "\r\n";
echo 4503599627370496;
echo "\r\n";
echo pow(2, 52) == 4503599627370496 ? 'equal' : 'not equal';
echo "\r\n";
echo pow(2, 52) == 4503599627370500 ? 'equal' : 'not equal';
?>

Expected result:
----------------
4503599627370496
4503599627370496
equal
not equal


Actual result:
--------------
4503599627370500
4503599627370500
equal
not equal

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-10-01 16:14 UTC] jani@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.


 [2009-10-01 16:58 UTC] terrafrost at gmail dot com
Maybe you should reread my bug report instead of giving knee jerk reactions.  Do you even know what a mantissa is?  If you hit Ctrl + F5 on the webpage you cited, you'll come across that term.

Anyway, if the mantissa has 53 bits of precision, why is PHP only showing 48 bits?  Oh - but because the precision is "limited", I guess that's not really a problem, is it?

You know what else has "limited precision"?  32-bit integers.  Even though those support numbers from &#8722;2,147,483,648 to 2,147,483,647, I guess it's not really a problem if PHP's echo statement was only capable of showing numbers ranging from, say, -128 to 127.  After all, why waste an opportunity to arbitrarily and artificially reduce precision for no real reason what-so-ever!  And if anyone complains, just remind them that they, too, have a "limited precision"!
 [2009-10-01 18:12 UTC] rasmus@php.net
My main question here is what exactly you think we can do about this?  We aren't artificially limiting the precision.  We work with the OS we are on.  If you run your script on a 64-bit OS (Linux in my case) the output is:

4503599627370496
4503599627370496
equal
not equal

Which is what you are expecting, correct?

Run it on a 32-bit OS (Mac OSX 10.5 in my case) and the output is:

4.5035996273705E+15
4.5035996273705E+15
equal
not equal

This, of course, is not unique to PHP.  Try this Perl script on the same 32-bit box:

print 2**52;
print "\n";
print 4503599627370496;
print "\n";
if (2**52 == 4503599627370496) { print 'equal';  } else { print 'not equal'; }
print "\n";
if (2**52 == 4503599627370500) { print 'equal'; } else { print 'not equal'; }

And the output is:

4.5035996273705e+15
4.5035996273705e+15
equal
not equal

So, you will be filing the same bug against Perl, I guess?

And just for completeness, that Perl script on my 64-bit Linux box outputs:

4.5035996273705e+15
4503599627370496
equal
not equal

So, Perl is actually more broken than PHP here.
 [2009-10-01 19:53 UTC] terrafrost at gmail dot com
Hmmm - I didn't realize the output would be machine dependent nor did I know that Perl behaved similarly.  Given this, I guess I agree with the closure.  If there's a problem, I guess it's with the host system and not with PHP, itself.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 05 04:01:35 2025 UTC