Edit report at http://bugs.php.net/bug.php?id=54056&edit=1
ID: 54056 User updated by: mr_platelet+jin6vr at fastmail dot fm Reported by: mr_platelet+jin6vr at fastmail dot fm Summary: number_format returns an incorrect answer for certain parameters -Status: Feedback +Status: Open Type: Bug Package: Strings related Operating System: Linux PHP Version: 5.3.5 Block user comment: N Private report: N New Comment: Arbitrary precision is not needed, because in each of the two scripts, the numbers generated using pow can be perfectly represented as IEEE double-precision floating-point numbers. I'll add an extra line of code to the first script in order to explain better what the problem is. Here's the new script. ------------------- <?php $x = pow(2, -1074); # new line of code here: printf("This shows that \$x is not zero:\n %.53e\n\n", $x); $s = number_format($x, 1074, '.', ''); if(trim($s, '0') === '.') { print "\$s represents zero, which is wrong.\n"; } ------------------- On my system, the output of the script is: ------------------- This shows that $x is not zero: 4.94065645841246544176568792868221372365059802614324764e-324 $s represents zero, which is wrong. ------------------- $s definitely should not represent zero, because 1074 (the second argument of number_format) is exactly the number of decimal digits needed to perfectly represent 2 to the power of -1074. More generally, for any positive integer n, the number 2^-n can be perfectly represented in base 10 using n decimal digits, as can be seen by considering the following sequence: 2^-1 = 0.5 2^-2 = 0.25 2^-3 = 0.125 2^-4 = 0.0625 2^-5 = 0.03125 2^-6 = 0.015625 2^-7 = 0.0078125 2^-8 = 0.00390625 2^-9 = 0.001953125 Previous Comments: ------------------------------------------------------------------------ [2011-02-20 16:37:22] ras...@php.net I'm not sure what you are expecting here. number_format() is not an arbitrary precision function. You are limited by the double precision of your operating system. ------------------------------------------------------------------------ [2011-02-20 14:33:45] mr_platelet+jin6vr at fastmail dot fm The following script shows further problems with number_format. ------------------ <?php $count = 0; $wrong = 0; for($i = 319; $i <= 1074; $i++) { $s1 = number_format(pow(2, -$i), $i, '.', ''); $s2 = bcpow(2, -$i, $i); $s1 = trim($s1, '0'); $s2 = trim($s2, '0'); $count++; $wrong += ($s1 !== $s2); } print "Number of calculations: $count\n"; print "Number of wrong answers: $wrong\n"; ------------------ When I run the script, it prints: Number of calculations: 756 Number of wrong answers: 756 Some extra information. (1) When running each of the 2 scripts I've supplied, I used PHP's "-n" switch. (2) Here is the "configure" command I used when building PHP: --prefix=/usr/local/php/5.3.5 --disable-all --enable-bcmath ------------------------------------------------------------------------ [2011-02-20 14:17:59] mr_platelet+jin6vr at fastmail dot fm Description: ------------ In the script below, number_format returns a string representing zero, which is quite wrong. Test script: --------------- <?php $x = pow(2, -1074); $s = number_format($x, 1074, '.', ''); if(trim($s, '0') === '.') { print "\$s represents zero, which is wrong.\n"; } Expected result: ---------------- I expect to see no output. Actual result: -------------- The script outputs the following message: $s represents zero, which is wrong. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/bug.php?id=54056&edit=1