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

 ID:                 54056
 Updated by:         cataphr...@php.net
 Reported by:        mr_platelet+jin6vr at fastmail dot fm
 Summary:            number_format returns an incorrect answer for
                     certain parameters
-Status:             Open
+Status:             Wont fix
 Type:               Bug
 Package:            Strings related
 Operating System:   Linux
 PHP Version:        5.3.5
 Block user comment: N
 Private report:     N

 New Comment:

PHP's implementation of spprintf, used by number_format, admits (if I'm
reading the code right) a maximum of 318 digits for the 'f' mode and 319
for 'e'.



This is because PHP relies on a buffer with 500 bytes
(formatted_print.c) or 512 bytes (snprint.c and spprintf.c) to hold the
resulting conversion of the number, so a larger number of digits could
overflow the buffer.



Given this, we could increase the buffer, limit the number of digits, or
dynamically allocate the buffer. Given the near absence of interest in
such number of decimal places, the current solution of limiting the
number of digits seems appropriate.



Won't fix.


Previous Comments:
------------------------------------------------------------------------
[2011-02-20 17:19:45] mr_platelet+jin6vr at fastmail dot fm

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

------------------------------------------------------------------------
[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

Reply via email to