Edit report at http://bugs.php.net/bug.php?id=47168&edit=1
ID: 47168 Updated by: il...@php.net Reported by: exploringbinary at gmail dot com Summary: printf of floating point variable prints maximum of 40 decimal places -Status: Assigned +Status: Closed Type: Bug Package: Math related Operating System: * PHP Version: 5.2.9 Assigned To: iliaa Block user comment: N Private report: N New Comment: This bug has been fixed in SVN. Snapshots of the sources are packaged every three hours; this change will be in the next snapshot. You can grab the snapshot at http://snaps.php.net/. Thank you for the report, and for helping us make PHP better. Previous Comments: ------------------------------------------------------------------------ [2010-11-19 17:36:12] il...@php.net Automatic comment from SVN on behalf of iliaa Revision: http://svn.php.net/viewvc/?view=revision&revision=305561 Log: Fixed bug #47168 (printf of floating point variable prints maximum of 40 decimal places). ------------------------------------------------------------------------ [2009-04-30 14:44:43] exploringbinary at gmail dot com 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))); ?> ------------------------------------------------------------------------ [2009-04-30 03:48:24] ras...@php.net 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] ras...@php.net 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. ------------------------------------------------------------------------ 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/bug.php?id=47168 -- Edit this bug report at http://bugs.php.net/bug.php?id=47168&edit=1