ID:               47168
 User updated by:  exploringbinary at gmail dot com
 Reported By:      exploringbinary at gmail dot com
 Status:           Assigned
 Bug Type:         Math related
 Operating System: *
 PHP Version:      5.2.9
 Assigned To:      rasmus
 New Comment:

A reader of my blog pointed out that serialize and unserialize have
similar issues.  I ran some tests and discovered that 2^-143 is the
smallest negative power of two that PHP can serialize, and 2^-40 is the
smallest it can unserialize.

Here's are the testcases:


This code works — it prints

d:8.9683101716788292539118693330554632401936764280097009392452370
16894662929189507849514484405517578125E-44;

<?php
 //Serialize 2^-143
 $dyadic = //Compute as (2^-50)^2 * 2^-43 to break up
 0.00000000000000088817841970012523233890533447265625*
 0.00000000000000088817841970012523233890533447265625*
 0.0000000000001136868377216160297393798828125;
 echo serialize ($dyadic);
?>

This code fails — it prints

d:4.4841550858394146269559346665277316200968382140048504696226185
08447331464594753924757242202758789062E-44;

<?php
 //Serialize 2^-144
 $dyadic = //Compute as (2^-50)^2 * 2^-44 to break up
 0.00000000000000088817841970012523233890533447265625*
 0.00000000000000088817841970012523233890533447265625*
 0.00000000000005684341886080801486968994140625;
 echo serialize ($dyadic);
?>

This code works — it prints

0.0000000000009094947017729282379150390625

<?php
 //Serialize and unserialize 2^-40
 $dyadic = 0.0000000000009094947017729282379150390625;
 printf ("%1.40f",unserialize(serialize($dyadic)));
?>

This code fails — it prints

Fails, prints 0.0000000000004547473508864641189575195312

<?php
 //Serialize and unserialize 2^-41
 $dyadic = 0.00000000000045474735088646411895751953125;
 printf ("%1.41f",unserialize(serialize($dyadic)));
?>


Previous Comments:
------------------------------------------------------------------------

[2009-04-30 03:48:24] [email protected]

There are a couple of other places that need to be changed.  I have a
patch but I haven't had a chance to go through and fix the test cases
yet.  I'll get to it before RC2 next week.

------------------------------------------------------------------------

[2009-04-30 01:23:58] ivan dot rey at inpltda dot com

I agree also.
Full precision should be available for the developer.

I wonder if recompiling php with a different CAP in  In
php-5.2.8\ext\standard\formatted_print.c I found this:
#define MAX_FLOAT_PRECISION 40 is the actual solution or if it has some
further implications.

------------------------------------------------------------------------

[2009-04-29 05:21:05] [email protected]

I agree with Rick here.  The 40-digit limit is strangely arbitrary and
doesn't match the size of the double.  We are hiding available precision
here.

------------------------------------------------------------------------

[2009-01-30 21:51:56] exploringbinary at gmail dot com

Since I didn't find anything in the documentation, I poked around in
the source code. In php-5.2.8\ext\standard\formatted_print.c I found
this: #define MAX_FLOAT_PRECISION 40

There is no explanation as to why it's capped at 40.

What's interesting is that this code prints only 40 decimal places
(0.0000000000004547473508864641189575195312), without a warning:

<?php
 /* Print 2^-41 */
 $dyadic = 0.00000000000045474735088646411895751953125;
 printf ("%1.2147483646f",$dyadic);
?>

While this code prints ``Warning: printf() [function.printf]: Precision
must be greater than zero and less than 2147483647 ...'' 

<?php
 /* Print 2^-41 */
 $dyadic = 0.00000000000045474735088646411895751953125;
 printf ("%1.2147483647f",$dyadic);
?>

If you're going to warn about a maximum, why not warn about the real
maximum -- 40, not 2147483646?

I wrote an article about how this issue is handled in PHP and 7 other
languages at
http://www.exploringbinary.com/print-precision-of-dyadic-fractions-varies-by-language/

------------------------------------------------------------------------

[2009-01-20 22:26:19] exploringbinary at gmail dot com

Hi,

  I read the documentation and the "how to submit a bug report" and
googled as well before (and now again after) submitting the bug report. 
I cannot see discussion of this limit. Could you please give me a more
specific link?

  I would also like to know the rationale for the limit. Why doesn't
javascript or gcc have this limit? Why did Microsoft accept my bug
report for a similar problem in VS? It seems like something PHP should
consider, or at least give rationale for why not.

Thanks.

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/47168

-- 
Edit this bug report at http://bugs.php.net/?id=47168&edit=1

Reply via email to