[php-maint] Bug#614001: number_format loses precision for certain numbers
Ronan
mr_platelet+jin6vr at fastmail.fm
Fri Feb 18 20:30:14 UTC 2011
Package: php5-cli
Version: 5.3.3-7
Severity: normal
number_format returns an incorrect answer for certain
numbers.
that there is at least one such number is shown in
the first included file, transcript1. it contains
a terminal transcript, and should be self-explanatory.
the second included file, transcript2, also contains
a terminal transcript. it shows that number_format
is buggy for 2^(-n), where n ranges over all the
integers in the interval [319, 1074].
*** transcript1
Script started on Fri 18 Feb 2011 20:26:17 GMT
bash$ PS1='>>>>>>>>>>>>>>>>>>>> '
>>>>>>>>>>>>>>>>>>>> cat demo1
#!/usr/bin/php5 -n
<?php
error_reporting(-1);
$x = pow(2, -1074);
/*
without this function, we would be
printing very wide strings, which would
make the window unacceptably wide for
people viewing Debian bugs in a web
browser
*/
function break_and_print($s) {
$s = wordwrap($s, 50, "\n", TRUE);
print rtrim($s) . "\n\n";
}
/*
the number printed here is
the same as $x
*/
break_and_print(bcpow(2, -1074, 1074));
/*
this prints zero, which is wrong
*/
break_and_print(number_format($x, 1074, '.', ''));
/*
this prints a non-zero number; therefore,
the bug is in number_format, not in the
`pow' function or the CPU
*/
printf("%e\n", $x);
>>>>>>>>>>>>>>>>>>>> php5 -n demo1
0.000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000004940656458412465441765687
92868221372365059802614324764425585682500675507270
20875186529983636163599237979656469544571773092665
67103559397963987747960107818781263007131903114045
27845817167848982103688718636056998730723050006387
40915356498438731247339727316961514003171538539807
41262385655911710266585566867681870395603106249319
45271591492455329305456544401127480129709999541931
98940908041656332452475714786901472678015935523861
15501348035264934720193790268107107491703332226844
75333572083243193609238289345836806010601150616980
97530783422773183292479049825247307763759272478746
56084778203734469699533647017972677717585125660551
19913150489110145103786273816725095583738973359899
36648099411642057026370902792427675445652290875386
82506419718265533447265625
0.000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000000000000000
4.940656e-324
>>>>>>>>>>>>>>>>>>>> exit
Script done on Fri 18 Feb 2011 20:26:31 GMT
*** transcript2
Script started on Fri 18 Feb 2011 20:05:55 GMT
bash$ PS1='>>>>>>>>>>>>>>>>>>>> '
>>>>>>>>>>>>>>>>>>>> cat demo2
#!/usr/bin/php5 -n
<?php
error_reporting(-1);
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');
/*
from a mathematical point of view,
this changes nothing, but it ensures
that the forthcoming string comparison
will work
*/
if($s1 === $s2) {
/*
this should be printed, because the
above condition should be true; but
it isn't true, which means there is
a bug
*/
print "\$s1 == \$s2 when \$i == $i\n";
}
}
>>>>>>>>>>>>>>>>>>>> php5 -n demo2
>>>>>>>>>>>>>>>>>>>> exit
Script done on Fri 18 Feb 2011 20:06:05 GMT
-- System Information:
Debian Release: 6.0
APT prefers stable
APT policy: (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.26-2-686 (SMP w/1 CPU core)
Locale: LANG=en_IE.UTF-8, LC_CTYPE=en_IE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages php5-cli depends on:
ii libbz2-1.0 1.0.5-6 high-quality block-sorting file co
ii libc6 2.11.2-10 Embedded GNU C Library: Shared lib
ii libcomerr2 1.41.12-2 common error description library
ii libdb4.8 4.8.30-2 Berkeley v4.8 Database Libraries [
ii libgssapi-krb5-2 1.8.3+dfsg-4 MIT Kerberos runtime libraries - k
ii libk5crypto3 1.8.3+dfsg-4 MIT Kerberos runtime libraries - C
ii libkrb5-3 1.8.3+dfsg-4 MIT Kerberos runtime libraries
ii libmagic1 5.04-5 File type determination library us
ii libonig2 5.9.1-1 Oniguruma regular expressions libr
ii libpcre3 8.02-1.1 Perl 5 Compatible Regular Expressi
ii libqdbm14 1.8.77-4 QDBM Database Libraries [runtime]
ii libssl0.9.8 0.9.8o-4squeeze1 SSL shared libraries
ii libxml2 2.7.8.dfsg-2 GNOME XML library
ii mime-support 3.48-1 MIME files 'mime.types' & 'mailcap
ii php5-common 5.3.3-7 Common files for packages built fr
ii tzdata 2010o-1 time zone and daylight-saving time
ii ucf 3.0025+nmu1 Update Configuration File: preserv
ii zlib1g 1:1.2.3.4.dfsg-3 compression library - runtime
php5-cli recommends no packages.
Versions of packages php5-cli suggests:
ii php-pear 5.3.3-7 PEAR - PHP Extension and Applicati
-- no debconf information
More information about the pkg-php-maint
mailing list