Closed p5pRT closed 20 years ago
This is a bug report for perl from greg_trott@raytheon.com\, generated with the help of perlbug 1.33 running under perl v5.6.1.
printf is inconsistent in its handling of decimal integer output. It seems to round certain values but not others. For example:
################################################## #!/usr/bin/perl -w
$thisval = (2.01)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.02)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.03)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.04)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (3.01)*(10**2); printf "thisval decimal = %d\n"\, $thisval; ##################################################
Output:
thisval decimal = 200 thisval decimal = 202 thisval decimal = 202 thisval decimal = 204 thisval decimal = 301
Expected output:
thisval decimal = 201 thisval decimal = 202 thisval decimal = 203 thisval decimal = 204 thisval decimal = 301
I've seen this problem using perl v5.6.1 on Solaris (see below) and also using v5.8.3 on Windows 2000.
Flags: category=core severity=medium
Site configuration information for perl v5.6.1:
Configured by smcadams at Tue Feb 26 16:33:08 EST 2002.
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=solaris\, osvers=2.5.1\, archname=sun4-solaris-thread-multi uname='sunos slpyyh 5.5.1 generic_103640-39 sun4u sparc sunw\,ultra-5_10 ' config_args='-Dusethreads -Dprefix=/usr/site/perl-5.6.1' hint=recommended\, useposix=true\, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='gcc'\, ccflags =' '\, optimize='-O'\, cppflags='' ccversion=''\, gccversion='2.8.1'\, gccosandvers='solaris2.6' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=4321 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4 alignbytes=8\, usemymalloc=y\, prototype=define Linker and Libraries: ld='gcc'\, ldflags =' ' libpth=/usr/lib libs=-lsocket -lnsl -ldl -lm -lposix4 -lpthread -lc perllibs=-lsocket -lnsl -ldl -lm -lposix4 -lpthread -lc libc=/lib/libc.so\, so=so\, useshrplib=false\, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' ' cccdlflags='-fPIC'\, lddlflags='-G'
Locally applied patches:
@INC for perl v5.6.1: /usr/site/perl-5.6.1/lib/5.6.1/sun4-solaris-thread-multi /usr/site/perl-5.6.1/lib/5.6.1 /usr/site/perl-5.6.1/lib/site_perl/5.6.1/sun4-solaris-thread-multi /usr/site/perl-5.6.1/lib/site_perl/5.6.1 /usr/site/perl-5.6.1/lib/site_perl .
Environment for perl v5.6.1: HOME=/home/oatmealu2/gtrott LANG=C LANGUAGE (unset) LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/usr/dt/lib:/usr/openwin/lib:/usr/lib/X11:/usr/X11R5/lib:./ LOGDIR (unset) PATH=/usr/sbin:/usr/j2se/bin:/usr/bin:/usr/openwin/bin:/usr/local/bin:/opt/SUNWspro/bin:/usr/ucb:/usr/etc:/usr:/usr/bin/X11:/bin:/usr/budtool/bin:/usr/atria/bin:/usr/local/flexlm/bin:/usr/ccs/bin:/home/oatmealu2/gtrott/bin:.:/home/oatmealu2/gtrott/CROP/ant.sun/apache-ant-1.5.3-1/bin PERL_BADLANG (unset) SHELL=/bin/csh
Thank you for your report.
However\, this is not a bug. It's a frequent problem when dealing with floating point numbers. Most floating point numbers\, such as 2.01\, do not have an exact binary representation:
mhx@r2d2 $ perl -e 'printf "%.20f\n"\, $_ for 2.01\, 2.02\, 2.03\, 2.04' 2.00999999999999978684 2.02000000000000001776 2.02999999999999980460 2.04000000000000003553
(When you're doing arithmetics on floating point values\, chances are good that they lose even more precision.)
Additionally\, you're using the %d format. This format represents a signed integer value (see perldoc -f sprintf). As your value is a floating point value\, it is forced into an integer value before printing. This is _not_ done by rounding\, but by truncating the floating point value. Thus your "wrong" results.
To get your expected results\, use the %f format. You can specify a precision in number of decimal (0 in your case)\, and this will actually round the values:
mhx@r2d2 $ perl -e 'printf "%.0f\n"\, (10**2)*$_ for 2.01\, 2.02\, 2.03\, 2.04' 201 202 203 204
Marcus
The RT System itself - Status changed from 'new' to 'open'
@mhx - Status changed from 'open' to 'resolved'
On Mon\, Apr 05\, 2004 at 06:29:05PM -0000\, greg_trott@raytheon.com (via RT) wrote:
# New Ticket Created by greg_trott@raytheon.com # Please include the string: [perl #28267] # in the subject line of all future correspondence about this issue. # \<URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=28267 >
This is a bug report for perl from greg_trott@raytheon.com\, generated with the help of perlbug 1.33 running under perl v5.6.1.
----------------------------------------------------------------- printf is inconsistent in its handling of decimal integer output. It seems to round certain values but not others. For example:
################################################## #!/usr/bin/perl -w
$thisval = (2.01)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.02)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.03)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (2.04)*(10**2); printf "thisval decimal = %d\n"\, $thisval;
$thisval = (3.01)*(10**2); printf "thisval decimal = %d\n"\, $thisval; ##################################################
Thank you for your report. However\, this is not a bug. First\, %d does not round\, it truncates. If you want to round\, you should use %f. Second\, perlfaq4 explains why floating point numbers may not behave as you expect:
Why am I getting long decimals (eg\, 19.9499999999999) instead of the numbers I should be getting (eg\, 19.95)?
Internally\, your computer represents floating-point numbers in binary. Digital (as in powers of two) computers cannot store all numbers exactly. Some real numbers lose precision in the process. This is a problem with how computers store numbers and affects all computer languages\, not just Perl.
perlnumber show the gory details of number representations and conversions.
To limit the number of decimal places in your numbers\, you can use the printf or sprintf function. See the "Floating Point Arithmetic" for more details.
printf "%.2f"\, 10/3;
my $number = sprintf "%.2f"\, 10/3;
HTH\, Ronald
Migrated from rt.perl.org#28267 (status was 'resolved')
Searchable as RT28267$