Perl / perl5

đŸȘ The Perl programming language
https://dev.perl.org/perl5/
Other
1.88k stars 531 forks source link

Rounding a floating point number #12451

Closed p5pRT closed 7 years ago

p5pRT commented 11 years ago

Migrated from rt.perl.org#115092 (status was 'rejected')

Searchable as RT115092$

p5pRT commented 11 years ago

From bk@starlink.ru

Created by bk@starlink.ru

I'm using the current version of Perl for CentOS el6 (5.10.1).

After moving to x64 architecture the behaviour of sprintf has been changed.

On this platform (x86) the output is like the following​:

# perl -e 'printf("%.2f"\, 6.685);' 6.68

But on the other (x64) platform I got this​:

# perl -e 'printf("%.2f"\, 6.685);' 6.69

I concatenated the output of perlbug from the x64 platform​:

!!!!!!!!!!!!!!! BEGIN x64 !!!!!!!!!!!!!!!!!!!!!!!!!

--- Flags​:   category=core   severity=low --- This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Fri Jun 22 13​:26​:34 UTC 2012.

Site configuration information for perl 5.10.1​:

Configured by Red Hat\, Inc. at Fri Jun 22 13​:26​:34 UTC 2012.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

  Platform​:   osname=linux\, osvers=2.6.32-220.el6.x86_64\, archname=x86_64-linux-thread-multi   uname='linux c6b7.bsys.dev.centos.org 2.6.32-220.el6.x86_64 #1 smp tue dec 6 19​:48​:22 gmt 2011 x86_64 x86_64 x86_64 gnulinux '   config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib64/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib64/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -! Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin -Dusesitecustomize'   hint=recommended\, useposix=true\, d_sigaction=define   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=define\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\,   optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'\,   cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'   ccversion=''\, gccversion='4.4.6 20120305 (Red Hat 4.4.6-4)'\, gccosandvers=''   intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16   ivtype='long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='gcc'\, ldflags =' -fstack-protector'   libpth=/usr/local/lib64 /lib64 /usr/lib64   libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc   perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc   libc=\, so=so\, useshrplib=true\, libperl=libperl.so   gnulibc_version='2.12'   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib64/perl5/CORE'   cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Locally applied patches​:

--- @​INC for perl 5.10.1​:   /usr/local/lib64/perl5   /usr/local/share/perl5   /usr/lib64/perl5/vendor_perl   /usr/share/perl5/vendor_perl   /usr/lib64/perl5   /usr/share/perl5   .

--- Environment for perl 5.10.1​:   HOME=/root   LANG=en_US.UTF-8   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/root/bin   PERL_BADLANG (unset)   SHELL=/bin/bash

!!!!!!!!!!!!!!! END x64 !!!!!!!!!!!!!!!!!!!!!!!!!

x32 platform-related stuff​:

Perl Info ``` Flags: category=core severity=low This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Sun Nov 6 00:21:10 GMT 2011. Site configuration information for perl 5.10.1: Configured by Red Hat, Inc. at Sun Nov 6 00:21:10 GMT 2011. Summary of my perl5 (revision 5 version 10 subversion 1) configuration: Platform: osname=linux, osvers=2.6.32-44.2.el6.x86_64, archname=i386-linux-thread-multi uname='linux c6b5.bsys.dev.centos.org 2.6.32-44.2.el6.x86_64 #1 smp wed jul 21 12:48:32 edt 2010 i686 i686 i386 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=i386-linux-thread-multi -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_! r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin' hint=recommended, useposix=true, d_sigaction=define useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=undef, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables', cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.4.5 20110214 (Red Hat 4.4.5-6)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='gcc', ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib/libc-2.12.so, so=so, useshrplib=true, libperl=libperl.so gnulibc_version='2.12' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/CORE' cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -L/usr/local/lib' Locally applied patches: @INC for perl 5.10.1: /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 . Environment for perl 5.10.1: HOME=/root LANG=ru_RU.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 11 years ago

From @jkeenan

On Mon Oct 01 04​:32​:45 2012\, bk@​starlink.ru wrote​:

This is a bug report for perl from bk@​starlink.ru\, generated with the help of perlbug 1.39 running under perl 5.10.1.

----------------------------------------------------------------- [Please describe your issue here]

I'm using the current version of Perl for CentOS el6 (5.10.1).

After moving to x64 architecture the behaviour of sprintf has been changed.

On this platform (x86) the output is like the following​:

# perl -e 'printf("%.2f"\, 6.685);' 6.68

But on the other (x64) platform I got this​:

# perl -e 'printf("%.2f"\, 6.685);' 6.69

I concatenated the output of perlbug from the x64 platform​:

!!!!!!!!!!!!!!! BEGIN x64 !!!!!!!!!!!!!!!!!!!!!!!!!

--- Flags​: category=core severity=low --- This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Fri Jun 22 13​:26​:34 UTC 2012.

Site configuration information for perl 5.10.1​:

Configured by Red Hat\, Inc. at Fri Jun 22 13​:26​:34 UTC 2012.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

Platform​: osname=linux\, osvers=2.6.32-220.el6.x86_64\, archname=x86_64-linux- thread-multi uname='linux c6b7.bsys.dev.centos.org 2.6.32-220.el6.x86_64 #1 smp tue dec 6 19​:48​:22 gmt 2011 x86_64 x86_64 x86_64 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib64/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib64/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -! Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin -Dusesitecustomize' hint=recommended\, useposix=true\, d_sigaction=define useithreads=define\, usemultiplicity=define useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef use64bitint=define\, use64bitall=define\, uselongdouble=undef usemymalloc=n\, bincompat5005=undef Compiler​: cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'\, cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion=''\, gccversion='4.4.6 20120305 (Red Hat 4.4.6-4)'\, gccosandvers='' intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=12345678 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16 ivtype='long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=8\, prototype=define Linker and Libraries​: ld='gcc'\, ldflags =' -fstack-protector' libpth=/usr/local/lib64 /lib64 /usr/lib64 libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=\, so=so\, useshrplib=true\, libperl=libperl.so gnulibc_version='2.12' Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib64/perl5/CORE' cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Locally applied patches​:

--- @​INC for perl 5.10.1​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .

--- Environment for perl 5.10.1​: HOME=/root LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset)

PATH=/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/root/bin PERL_BADLANG (unset) SHELL=/bin/bash

!!!!!!!!!!!!!!! END x64 !!!!!!!!!!!!!!!!!!!!!!!!!

x32 platform-related stuff​:

[Please do not change anything below this line] ----------------------------------------------------------------- --- Flags​: category=core severity=low --- This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Sun Nov 6 00​:21​:10 GMT 2011.

Site configuration information for perl 5.10.1​:

Configured by Red Hat\, Inc. at Sun Nov 6 00​:21​:10 GMT 2011.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

Platform​: osname=linux\, osvers=2.6.32-44.2.el6.x86_64\, archname=i386-linux- thread-multi uname='linux c6b5.bsys.dev.centos.org 2.6.32-44.2.el6.x86_64 #1 smp wed jul 21 12​:48​:32 edt 2010 i686 i686 i386 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=i386-linux-thread-multi -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_! r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin' hint=recommended\, useposix=true\, d_sigaction=define useithreads=define\, usemultiplicity=define useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef use64bitint=undef\, use64bitall=undef\, uselongdouble=undef usemymalloc=n\, bincompat5005=undef Compiler​: cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables'\, cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion=''\, gccversion='4.4.5 20110214 (Red Hat 4.4.5-6)'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, prototype=define Linker and Libraries​: ld='gcc'\, ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib/libc-2.12.so\, so=so\, useshrplib=true\, libperl=libperl.so gnulibc_version='2.12' Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib/perl5/CORE' cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -L/usr/local/lib'

Locally applied patches​:

--- @​INC for perl 5.10.1​: /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .

--- Environment for perl 5.10.1​: HOME=/root LANG=ru_RU.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset)

PATH=/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/root/bin PERL_BADLANG (unset) SHELL=/bin/bash

Three preliminary notes​:

1. Have you ruled out any other possible cause of this difference? I notice that you are using different versions of gcc on the two platforms.

2. You are running an older\, unsupported version of Perl. Can you run this with either 5.14 or 5.16? (Note​: I'm not saying the Perl version is the cause of the difference. It's just that a flaw in 5.10 is not going to be corrected.)

3. At the moment I have no x86_64 machine available. I do have a Darwin/PPC and a Linux/i386. Both are running Perl 5.16\, but they're probably running different versions of gcc. I get​:

Darwin/PPC​:

perl -E 'printf("%.2f"\, 6.685);' 6.69

Linux/i386​:

perl -E 'printf("%.2f"\, 6.685);' 6.68

I suspect that the differences in the rounding is not Perl's problems -- but there are others on list who can speak better to that.

Thank you very much. Jim Keenan

p5pRT commented 11 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Mon\, Oct 1\, 2012 at 10​:22 PM\, James E Keenan via RT \< perlbug-followup@​perl.org> wrote​:

On Mon Oct 01 04​:32​:45 2012\, bk@​starlink.ru wrote​:

This is a bug report for perl from bk@​starlink.ru\, generated with the help of perlbug 1.39 running under perl 5.10.1.

----------------------------------------------------------------- [Please describe your issue here]

I'm using the current version of Perl for CentOS el6 (5.10.1).

After moving to x64 architecture the behaviour of sprintf has been changed.

On this platform (x86) the output is like the following​:

# perl -e 'printf("%.2f"\, 6.685);' 6.68

But on the other (x64) platform I got this​:

# perl -e 'printf("%.2f"\, 6.685);' 6.69

Three preliminary notes​:

1. Have you ruled out any other possible cause of this difference? I notice that you are using different versions of gcc on the two platforms.

2. You are running an older\, unsupported version of Perl. Can you run this with either 5.14 or 5.16? (Note​: I'm not saying the Perl version is the cause of the difference. It's just that a flaw in 5.10 is not going to be corrected.)

3. At the moment I have no x86_64 machine available. I do have a Darwin/PPC and a Linux/i386. Both are running Perl 5.16\, but they're probably running different versions of gcc. I get​:

Darwin/PPC​:

perl -E 'printf("%.2f"\, 6.685);' 6.69

Linux/i386​:

perl -E 'printf("%.2f"\, 6.685);' 6.68

I suspect that the differences in the rounding is not Perl's problems -- but there are others on list who can speak better to that.

Thank you very much. Jim Keenan

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

It's more of a floating point gotcha than a perl issue.


via perlbug​: queue​: perl5 status​: new https://rt-archive.perl.org/perl5/Ticket/Display.html?id=11509 2

p5pRT commented 11 years ago

From @ikegami

On Tue\, Oct 2\, 2012 at 4​:58 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

He got the higher result on the x64 than the x86\, so that makes no sense. Why would the lower number give the higher rounded result?

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Oct 2\, 2012 5​:37 PM\, "Eric Brine" \ikegami@&#8203;adaelis\.com wrote​:

On Tue\, Oct 2\, 2012 at 4​:58 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

He got the higher result on the x64 than the x86\, so that makes no sense. Why would the lower number give the higher rounded result?

Ah. I wasn't paying enough attention to which was which. Printing to 20 (or 30) places will still show different approximations of 6.685 though\, depending on the fp hardware - can that be confirmed?

2.275 is another good one to test (if I recall correctly)

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Oct 2\, 2012 5​:48 PM\, "Peter Martini" \petercmartini@&#8203;gmail\.com wrote​:

On Oct 2\, 2012 5​:37 PM\, "Eric Brine" \ikegami@&#8203;adaelis\.com wrote​:

On Tue\, Oct 2\, 2012 at 4​:58 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

He got the higher result on the x64 than the x86\, so that makes no sense. Why would the lower number give the higher rounded result?

Ah. I wasn't paying enough attention to which was which. Printing to 20 (or 30) places will still show different approximations of 6.685 though\, depending on the fp hardware - can that be confirmed?

2.275 is another good one to test (if I recall correctly)

Yep\, tested on my android phone​:

javascript​:alert(2.275.toFixed(2))

displays 2.27.

My original test was Windows 7 Chrome\, and I'm pretty sure 64bit\, but not positive.

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Tue\, Oct 2\, 2012 at 5​:37 PM\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Tue\, Oct 2\, 2012 at 4​:58 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

He got the higher result on the x64 than the x86\, so that makes no sense. Why would the lower number give the higher rounded result?

More machines​:

(pmdesktop is 64-bit)

[peter@​pmdesktop ~]$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.69 / 6.685000000000000497379915032070

(pmlinlaptop is 32-bit)

peter@​pmlinlaptop​:\~$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

So the Chrome I was using at the time was probably 32-bit after all. Should have double checked :-)

p5pRT commented 11 years ago

From @ikegami

On Tue\, Oct 2\, 2012 at 6​:33 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

(pmdesktop is 64-bit) [peter@​pmdesktop ~]$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.69 / 6.685000000000000497379915032070

(This is perl 5\, version 16\, subversion 0 (v5.16.0) built for x86_64-linux-thread-multi) $ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

p5pRT commented 11 years ago

From @cpansprout

On Tue Oct 02 15​:33​:57 2012\, pcm wrote​:

On Tue\, Oct 2\, 2012 at 5​:37 PM\, Eric Brine \ikegami@&#8203;adaelis\.com wrote​:

On Tue\, Oct 2\, 2012 at 4​:58 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

For what it's worth\, I get the same behavior in javascript on Google Chrome on a 64-bit platform\, because 6.685 is stored internally as​:

"6.68499999999999960920"

Try perl -E 'printf("%.20f"\, 6.685)' to see what you're actually storing - the nearest number to 6.685 may be very slightly less than 6.685\, and hence round down.

I don't have a 32-bit platform to test at hand\, but I'd guess that on a 32-bit platform it's something more like​:

"6.68500000000000000001"

He got the higher result on the x64 than the x86\, so that makes no sense. Why would the lower number give the higher rounded result?

More machines​:

(pmdesktop is 64-bit)

[peter@​pmdesktop ~]$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.69 / 6.685000000000000497379915032070

(pmlinlaptop is 32-bit)

peter@​pmlinlaptop​:\~$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

So the Chrome I was using at the time was probably 32-bit after all. Should have double checked :-)

JavaScript should give the same result regardless of platform. ECMAScript is pretty strict about how floating-point operations work.

JE is probably the only non-compliant implementation.

--

Father Chrysostomos

p5pRT commented 11 years ago

From @ikegami

This is perl 5\, version 14\, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread

perl -e"printf qq{%.02f / %.30f\n}\, 6.685\, 6.685 6.69 / 6.685000000000000500000000000000

This is perl\, v5.10.1 (*) built for i686-cygwin-thread-multi-64int

$ perl -E'say sprintf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

(Both on the same 64-bit Win7 machine)

p5pRT commented 11 years ago

From @sisyphus

----- Original Message ----- From​: "Eric Brine" \ikegami@&#8203;adaelis\.com To​: "Peter Martini" \petercmartini@&#8203;gmail\.com Cc​: \perlbug\-followup@&#8203;perl\.org; \bk@&#8203;starlink\.ru; \perl5\-porters@&#8203;perl\.org Sent​: Wednesday\, October 03\, 2012 9​:13 AM Subject​: Re​: [perl #115092] Rounding a floating point number

On Tue\, Oct 2\, 2012 at 6​:33 PM\, Peter Martini \petercmartini@&#8203;gmail\.com wrote​:

(pmdesktop is 64-bit) [peter@​pmdesktop ~]$ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.69 / 6.685000000000000497379915032070

(This is perl 5\, version 16\, subversion 0 (v5.16.0) built for x86_64-linux-thread-multi) $ perl -e 'printf "%.02f / %.30f\n"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

FWIW\, for perls built with nvsize=8\, I get the same as Eric on both Linux (32-bit only) and Windows (32-bit and 64-bit). For perls built with nvsize=12\, I get a slightly different value for %.30f​:

6.684999999999999999947958295721

but it's still less than 6.685\, and rounds to 6.68.

However\, perhaps Peter's perl has an nvsize that is neither 8 nor 12 ?

On MS Windows\, I can use Math​::LongDouble to effectively obtain long double precision​:

########################################### C​:\_32>perl -MMath​::LongDouble="​:all" -e "$x=Math​::LongDouble->new(6.685);print LDtoSTRP($x\, 31)" 6.684999999999999999947958295721e+000 ###########################################

Cheers\, Rob

p5pRT commented 11 years ago

From @sisyphus

----- Original Message ----- From​: "Eric Brine" \ikegami@&#8203;adaelis\.com To​: "Peter Martini" \petercmartini@&#8203;gmail\.com Cc​: \perlbug\-followup@&#8203;perl\.org; \bk@&#8203;starlink\.ru; \perl5\-porters@&#8203;perl\.org Sent​: Wednesday\, October 03\, 2012 9​:19 AM Subject​: Re​: [perl #115092] Rounding a floating point number

This is perl 5\, version 14\, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread

perl -e"printf qq{%.02f / %.30f\n}\, 6.685\, 6.685 6.69 / 6.685000000000000500000000000000

Heh ... I didn't try ActivePerl ... but when I do\, I get the same​:

C​:\_32>perl -e "printf \"%.02f / %.30f\n\"\, 6.685\, 6.685" 6.69 / 6.685000000000000500000000000000

Cheers\, Rob

p5pRT commented 11 years ago

From @jandubois

On Tue\, 02 Oct 2012\, Sisyphus wrote​:

FWIW\, for perls built with nvsize=8\, I get the same as Eric on both Linux (32-bit only) and Windows (32-bit and 64-bit). For perls built with nvsize=12\, I get a slightly different value for %.30f​:

6.684999999999999999947958295721

but it's still less than 6.685\, and rounds to 6.68.

However\, perhaps Peter's perl has an nvsize that is neither 8 nor 12 ?

You may want to play around with the FPU rounding mode as well​:

  http​://msdn.microsoft.com/en-us/library/e9b52ceh%28v=vs.80%29.aspx

It is possible that a different RTL has set up a different rounding mode.

We do initialize the error mode on Windows to be independent of the RTL\, but maybe we should also select a default rounding mode​:

  /* Disable floating point errors\, Perl will trap the ones we   * care about. VC++ RTL defaults to switching these off   * already\, but some RTLs don't. Since we don't   * want to be at the vendor's whim on the default\, we set   * it explicitly here.   */ #if !defined(__GNUC__)   _control87(MCW_EM\, MCW_EM); #endif

Cheers\, -Jan

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Oct 2\, 2012 8​:31 PM\, "Jan Dubois" \jand@&#8203;activestate\.com wrote​:

On Tue\, 02 Oct 2012\, Sisyphus wrote​:

FWIW\, for perls built with nvsize=8\, I get the same as Eric on both Linux (32-bit only) and Windows (32-bit and 64-bit). For perls built with nvsize=12\, I get a slightly different value for %.30f​:

6.684999999999999999947958295721

but it's still less than 6.685\, and rounds to 6.68.

However\, perhaps Peter's perl has an nvsize that is neither 8 nor 12 ?

You may want to play around with the FPU rounding mode as well​:

http​://msdn.microsoft.com/en-us/library/e9b52ceh%28v=vs.80%29.aspx

It is possible that a different RTL has set up a different rounding mode.

We do initialize the error mode on Windows to be independent of the RTL\, but maybe we should also select a default rounding mode​:

/\* Disable floating point errors\, Perl will trap the ones we
 \* care about\.  VC\+\+ RTL defaults to switching these off
 \* already\, but some RTLs don't\.  Since we don't
 \* want to be at the vendor's whim on the default\, we set
 \* it explicitly here\.
 \*/

#if !defined(__GNUC__) _control87(MCW_EM\, MCW_EM); #endif

Would the rounding mode affect the atof? (honest question\, I don't know where it does its thing). The issue is the closest approximation is sometimes on the high side and sometimes on the low side\, depending on nvsize - and no matter what size you're using\, there will be numbers that round "wrong".

2.275 bit me in a javascript project years ago\, since it rounds to 2.27\, and that was enough for me to take seriously its limitations. Which means I don't think there's anything for us to do here. But javascripts standard size does get the op's example right :-)

Cheers\, -Jan

On Oct 2\, 2012 8​:31 PM\, "Jan Dubois" \jand@&#8203;activestate\.com wrote​:

On Tue\, 02 Oct 2012\, Sisyphus wrote​:

FWIW\, for perls built with nvsize=8\, I get the same as Eric on both Linux (32-bit only) and Windows (32-bit and 64-bit). For perls built with nvsize=12\, I get a slightly different value for %.30f​:

6.684999999999999999947958295721

but it's still less than 6.685\, and rounds to 6.68.

However\, perhaps Peter's perl has an nvsize that is neither 8 nor 12 ?

You may want to play around with the FPU rounding mode as well​:

http​://msdn.microsoft.com/en-us/library/e9b52ceh%28v=vs.80%29.aspx

It is possible that a different RTL has set up a different rounding mode.

We do initialize the error mode on Windows to be independent of the RTL\, but maybe we should also select a default rounding mode​:

/\* Disable floating point errors\, Perl will trap the ones we
 \* care about\.  VC\+\+ RTL defaults to switching these off
 \* already\, but some RTLs don't\.  Since we don't
 \* want to be at the vendor's whim on the default\, we set
 \* it explicitly here\.
 \*/

#if !defined(__GNUC__) _control87(MCW_EM\, MCW_EM); #endif

Cheers\, -Jan

p5pRT commented 11 years ago

From @jkeenan

So\, do we have a Perl bug here?

p5pRT commented 11 years ago

From @cpansprout

On Tue Oct 02 18​:15​:43 2012\, jkeenan wrote​:

So\, do we have a Perl bug here?

Maybe. Could someone who sees different behaviour with different perls try replacing 6.685 with POSIX​::strtod("6.685")?

If the answer then becomes the same with different perls\, then I suspect this is a duplicate of #41202.

--

Father Chrysostomos

p5pRT commented 11 years ago

From PeterCMartini@GMail.com

On Tue\, Oct 2\, 2012 at 9​:21 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

On Tue Oct 02 18​:15​:43 2012\, jkeenan wrote​:

So\, do we have a Perl bug here?

Maybe. Could someone who sees different behaviour with different perls try replacing 6.685 with POSIX​::strtod("6.685")?

If the answer then becomes the same with different perls\, then I suspect this is a duplicate of #41202.

On my 64-bit machine​:

perl -E 'use POSIX qw(strtod); printf "%.02f\, %.02f\n"\, 6.685\, strtod("6.685");' 6.69\, 6.68

perl -E 'use POSIX qw(strtod); printf "%.020f\, %.020f\n"\, 6.685\, strtod("6.685");' 6.68500000000000049738\, 6.68499999999999960920

And for good measure\, on that same machine​:

File a.cpp #include \ #include \ #include \ using namespace std;

int main(){   cout \<\< setprecision(40) \<\< strtof("6.685"\,0) \<\< endl;   cout \<\< setprecision(40) \<\< strtod("6.685"\,0) \<\< endl;   cout \<\< setprecision(40) \<\< strtold("6.685"\,0) \<\< endl; }

gives me​:

6.684999942779541015625 6.684999999999999609201495331944897770882 6.684999999999999999947958295720695787168

So\, I'll dig through and see if where it got that number from. For the record\, both the system perl and one built with ./Configure -Dusedevel -Dusethreads -des do the same thing\, and here's perl -V from the system perl​:

  Platform​:   osname=linux\, osvers=2.6.32-220.el6.x86_64\, archname=x86_64-linux-thread-multi   uname='linux c6b7.bsys.dev.centos.org 2.6.32-220.el6.x86_64 #1 smp tue dec 6 19​:48​:22 gmt 2011 x86_64 x86_64 x86_64 gnulinux '   config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size =4 -m64 -mtune=generic -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib64/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib64/perl5/vend or_perl -Dinc_version_list=5.10.0 -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -D usethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r _proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dscri ptdir=/usr/bin -Dusesitecustomize'   hint=recommended\, useposix=true\, d_sigaction=define   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=define\, use64bitall=define\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\,   optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'\,   cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'   ccversion=''\, gccversion='4.4.6 20120305 (Red Hat 4.4.6-4)'\, gccosandvers=''   intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=12345678   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16   ivtype='long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='gcc'\, ldflags =' -fstack-protector'   libpth=/usr/local/lib64 /lib64 /usr/lib64   libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc   perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc   libc=\, so=so\, useshrplib=true\, libperl=libperl.so   gnulibc_version='2.12'   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib64/perl5/CORE'   cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY PERL_DONT_CREATE_GVSV   PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP USE_64_BIT_ALL   USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES   USE_PERLIO USE_REENTRANT_API USE_SITECUSTOMIZE   Built under linux   Compiled at Jun 22 2012 13​:27​:28   @​INC​:   /usr/local/lib64/perl5   /usr/local/share/perl5   /usr/lib64/perl5/vendor_perl   /usr/share/perl5/vendor_perl   /usr/lib64/perl5   /usr/share/perl5   .

--

Father Chrysostomos

--- via perlbug​: queue​: perl5 status​: open https://rt-archive.perl.org/perl5/Ticket/Display.html?id=115092

p5pRT commented 11 years ago

From @cpansprout

On Tue Oct 02 20​:41​:15 2012\, pcm wrote​:

On Tue\, Oct 2\, 2012 at 9​:21 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

On Tue Oct 02 18​:15​:43 2012\, jkeenan wrote​:

So\, do we have a Perl bug here?

Maybe. Could someone who sees different behaviour with different perls try replacing 6.685 with POSIX​::strtod("6.685")?

If the answer then becomes the same with different perls\, then I suspect this is a duplicate of #41202.

On my 64-bit machine​:

perl -E 'use POSIX qw(strtod); printf "%.02f\, %.02f\n"\, 6.685\, strtod("6.685");' 6.69\, 6.68

perl -E 'use POSIX qw(strtod); printf "%.020f\, %.020f\n"\, 6.685\, strtod("6.685");' 6.68500000000000049738\, 6.68499999999999960920

And for good measure\, on that same machine​:

File a.cpp #include \ #include \ #include \ using namespace std;

int main(){ cout \<\< setprecision(40) \<\< strtof("6.685"\,0) \<\< endl; cout \<\< setprecision(40) \<\< strtod("6.685"\,0) \<\< endl; cout \<\< setprecision(40) \<\< strtold("6.685"\,0) \<\< endl; }

gives me​:

6.684999942779541015625 6.684999999999999609201495331944897770882 6.684999999999999999947958295720695787168

So\, I'll dig through and see if where it got that number from.

If you mean the 6.69\, it’s coming from numeric.c​:Perl_grok_number. Perl has it’s own string-to-number conversion which\, er\, doesn’t work. That’s the subject of ticket #41202. I don’t have the expertise to fix it\, and unfortunately it seems nobody here does.

--

Father Chrysostomos

p5pRT commented 11 years ago

From explorer@joaquinferrero.com

El 03/10/12 03​:15\, James E Keenan via RT escribiĂł​:

So\, do we have a Perl bug here?

I like the idea for a computer language with True Math...

(just dreaming)

-- JF^D

p5pRT commented 11 years ago

From @ikegami

On Tue\, Oct 2\, 2012 at 9​:21 PM\, Father Chrysostomos via RT \perlbug\-followup@&#8203;perl\.org wrote​:

Maybe. Could someone who sees different behaviour with different perls try replacing 6.685 with POSIX​::strtod("6.685")?

Here you go​:

[ActivePerl] This is perl 5\, version 14\, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread

perl -E"say sprintf '%.2f / %.30f'\, (6.685)x2 6.69 / 6.685000000000000500000000000000

perl -MPOSIX=strtod -E"say sprintf '%.2f\, %.30f'\, (''.strtod('6.685'))x2" 6.69\, 6.685000000000000500000000000000

[Cygwin] This is perl\, v5.10.1 (*) built for i686-cygwin-thread-multi-64int

$ perl -E'say sprintf "%.2f / %.30f"\, 6.685\, 6.685' 6.68 / 6.684999999999999609201495331945

$ perl -MPOSIX=strtod -E'say sprintf "%.2f / %.30f"\, ("".strtod("6.685"))x2' 6.68 / 6.684999999999999609201495331945

Both on the same 64-bit Win7 machine.

p5pRT commented 11 years ago

From @salva

On 10/02/2012 04​:22 AM\, James E Keenan via RT wrote​:

On Mon Oct 01 04​:32​:45 2012\, bk@​starlink.ru wrote​:

This is a bug report for perl from bk@​starlink.ru\, generated with the help of perlbug 1.39 running under perl 5.10.1.

----------------------------------------------------------------- [Please describe your issue here]

I'm using the current version of Perl for CentOS el6 (5.10.1).

After moving to x64 architecture the behaviour of sprintf has been changed.

On this platform (x86) the output is like the following​:

# perl -e 'printf("%.2f"\, 6.685);' 6.68

But on the other (x64) platform I got this​:

# perl -e 'printf("%.2f"\, 6.685);' 6.69

I concatenated the output of perlbug from the x64 platform​:

!!!!!!!!!!!!!!! BEGIN x64 !!!!!!!!!!!!!!!!!!!!!!!!!

--- Flags​: category=core severity=low --- This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Fri Jun 22 13​:26​:34 UTC 2012.

Site configuration information for perl 5.10.1​:

Configured by Red Hat\, Inc. at Fri Jun 22 13​:26​:34 UTC 2012.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

Platform​: osname=linux\, osvers=2.6.32-220.el6.x86_64\, archname=x86_64-linux- thread-multi uname='linux c6b7.bsys.dev.centos.org 2.6.32-220.el6.x86_64 #1 smp tue dec 6 19​:48​:22 gmt 2011 x86_64 x86_64 x86_64 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib64/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib64/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib64/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=x86_64-linux-thread-multi -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -! Ud_endservent_r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin -Dusesitecustomize' hint=recommended\, useposix=true\, d_sigaction=define useithreads=define\, usemultiplicity=define useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef use64bitint=define\, use64bitall=define\, uselongdouble=undef usemymalloc=n\, bincompat5005=undef Compiler​: cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'\, cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion=''\, gccversion='4.4.6 20120305 (Red Hat 4.4.6-4)'\, gccosandvers='' intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=12345678 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16 ivtype='long'\, ivsize=8\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=8\, prototype=define Linker and Libraries​: ld='gcc'\, ldflags =' -fstack-protector' libpth=/usr/local/lib64 /lib64 /usr/lib64 libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=\, so=so\, useshrplib=true\, libperl=libperl.so gnulibc_version='2.12' Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib64/perl5/CORE' cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

Locally applied patches​:

--- @​INC for perl 5.10.1​: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .

--- Environment for perl 5.10.1​: HOME=/root LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset)

PATH=/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/root/bin PERL_BADLANG (unset) SHELL=/bin/bash

!!!!!!!!!!!!!!! END x64 !!!!!!!!!!!!!!!!!!!!!!!!!

x32 platform-related stuff​:

[Please do not change anything below this line] ----------------------------------------------------------------- --- Flags​: category=core severity=low --- This perlbug was built using Perl 5.10.1 in the Fedora build system. It is being executed now by Perl 5.10.1 - Sun Nov 6 00​:21​:10 GMT 2011.

Site configuration information for perl 5.10.1​:

Configured by Red Hat\, Inc. at Sun Nov 6 00​:21​:10 GMT 2011.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:

Platform​: osname=linux\, osvers=2.6.32-44.2.el6.x86_64\, archname=i386-linux- thread-multi uname='linux c6b5.bsys.dev.centos.org 2.6.32-44.2.el6.x86_64 #1 smp wed jul 21 12​:48​:32 edt 2010 i686 i686 i386 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DDEBUGGING=-g -Dversion=5.10.1 -Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc -Dcf_by=Red Hat\, Inc. -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl5 -Dsitearch=/usr/local/lib/perl5 -Dprivlib=/usr/share/perl5 -Darchlib=/usr/lib/perl5 -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib/perl5/vendor_perl -Dinc_version_list=5.10.0 -Darchname=i386-linux-thread-multi -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_! r_proto -Ud_setservent_r_proto -Dscriptdir=/usr/bin' hint=recommended\, useposix=true\, d_sigaction=define useithreads=define\, usemultiplicity=define useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef use64bitint=undef\, use64bitall=undef\, uselongdouble=undef usemymalloc=n\, bincompat5005=undef Compiler​: cc='gcc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\, optimize='-O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables'\, cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion=''\, gccversion='4.4.5 20110214 (Red Hat 4.4.5-6)'\, gccosandvers='' intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234 d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12 ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8 alignbytes=4\, prototype=define Linker and Libraries​: ld='gcc'\, ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib/libc-2.12.so\, so=so\, useshrplib=true\, libperl=libperl.so gnulibc_version='2.12' Dynamic Linking​: dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-Wl\,-E -Wl\,-rpath\,/usr/lib/perl5/CORE' cccdlflags='-fPIC'\, lddlflags='-shared -O2 -g -pipe -Wall -Wp\,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -L/usr/local/lib'

Locally applied patches​:

--- @​INC for perl 5.10.1​: /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .

--- Environment for perl 5.10.1​: HOME=/root LANG=ru_RU.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset)

PATH=/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/root/bin PERL_BADLANG (unset) SHELL=/bin/bash

Three preliminary notes​:

1. Have you ruled out any other possible cause of this difference? I notice that you are using different versions of gcc on the two platforms.

2. You are running an older\, unsupported version of Perl. Can you run this with either 5.14 or 5.16? (Note​: I'm not saying the Perl version is the cause of the difference. It's just that a flaw in 5.10 is not going to be corrected.)

3. At the moment I have no x86_64 machine available. I do have a Darwin/PPC and a Linux/i386. Both are running Perl 5.16\, but they're probably running different versions of gcc. I get​:

Darwin/PPC​:

perl -E 'printf("%.2f"\, 6.685);' 6.69

Linux/i386​:

perl -E 'printf("%.2f"\, 6.685);' 6.68

I suspect that the differences in the rounding is not Perl's problems -- but there are others on list who can speak better to that.

This difference is probably caused by the way x86 stores floating point values internal using 80 bits.

On the x86_64 floating point operation can also be done in 80 bits\, but the code generated by gcc uses the mmx registers that are 64 bits.

AFAIK\, most other architectures (ARM\, MIPS\, PPC\, SPARC) also represent doubles using 64 bits.

p5pRT commented 11 years ago

From @bulk88

Looking at this thread\, how will this bug be closed? I think there are 3 options on the table to be taken.

1. Not a Perl bug\, close as rejected\, file a bug with your OS\, C compiler\, or CPU vendor\, add a couple sentences to perlport or perldata about "FP/NVs are OS and CPU specific" disclaimer. Con​: Perl scripts aren't portable now.

2. Fix the makefiles on different Perl platforms to use the same FP behavior if supported by the CPU/compiler. Con​: What to do about CPUs/compilers that aren't compliant? Deprecate and remove platforms? How would SPARCs\, Itaniums\, Power/PowerPC\, and ARMs behave with FP rounding in Perl?

3. Add a pure software FP library so FP on all Perl platforms is identical and reproducible perfectly. Con​: Perl's abysmal scientific computing/multimedia performance will be even slower.

p5pRT commented 11 years ago

From @jandubois

On Thu\, 04 Oct 2012\, bulk 88 via RT wrote​:

Looking at this thread\, how will this bug be closed? I think there are 3 options on the table to be taken.

1. Not a Perl bug\, close as rejected\, file a bug with your OS\, C compiler\, or CPU vendor\, add a couple sentences to perlport or perldata about "FP/NVs are OS and CPU specific" disclaimer. Con​: Perl scripts aren't portable now.

Maybe not a Perl bug\, but as Larry Wall once wrote​: "The Golden Gate wasn't our fault either\, but we still put a bridge across it."

2. Fix the makefiles on different Perl platforms to use the same FP behavior if supported by the CPU/compiler. Con​: What to do about CPUs/compilers that aren't compliant? Deprecate and remove platforms? How would SPARCs\, Itaniums\, Power/PowerPC\, and ARMs behave with FP rounding in Perl?

Perl should hide platform differences as much as possible\, and document the remaining ones in perlport.pod.

3. Add a pure software FP library so FP on all Perl platforms is identical and reproducible perfectly. Con​: Perl's abysmal scientific computing/multimedia performance will be even slower.

I don't think this is useful. Doesn't Math​::BigFloat already do this?

So *if* the problem turns out to be the floating point rounding mode used by the compiler/RTL\, then we should try to explicitly set a particular mode wherever we can.

Cheers\, -Jan

p5pRT commented 11 years ago

From greg@blekko.com

On Thu\, Oct 04\, 2012 at 10​:20​:33AM -0700\, bulk 88 via RT wrote​:

2. Fix the makefiles on different Perl platforms to use the same FP behavior if supported by the CPU/compiler. Con​: What to do about CPUs/compilers that aren't compliant? Deprecate and remove platforms? How would SPARCs\, Itaniums\, Power/PowerPC\, and ARMs behave with FP rounding in Perl?

And here it comes around again... btw the only platform afflicted with this problem is i386. And most compilers on i386 offered a flag like this a looooong time ago.

Date​: Sat\, 22 Jan 2011 14​:25​:23 -0800 From​: Greg Lindahl \greg@&#8203;blekko\.com To​: Chip Salzenberg \rev\.chip@&#8203;gmail\.com Cc​: p5p \perl5\-porters@&#8203;perl\.org Subject​: Re​: Being more careful with FP on gcc​: Message-ID​: \20110122222523\.GB14655@&#8203;bx9\.net

On Sat\, Jan 22\, 2011 at 08​:39​:13AM -0800\, Chip Salzenberg wrote​:

After carefully considering http​://blog.andreas.org/display?id=9 I believe we should add the flag "-fexcess-precision=standard" when compiling on gcc 4.5+. Any controversy here?

That flag is the right thing to do -- I'm surprised that it wasn't noticed earlier. It's not hard to write a little test in C so that we would know if other compilers need a similar switch\, too.

-- greg

p5pRT commented 11 years ago

From @doughera88

On Thu\, 4 Oct 2012\, Greg Lindahl wrote​:

On Thu\, Oct 04\, 2012 at 10​:20​:33AM -0700\, bulk 88 via RT wrote​:

2. Fix the makefiles on different Perl platforms to use the same FP behavior if supported by the CPU/compiler. Con​: What to do about CPUs/compilers that aren't compliant? Deprecate and remove platforms? How would SPARCs\, Itaniums\, Power/PowerPC\, and ARMs behave with FP rounding in Perl?

And here it comes around again... btw the only platform afflicted with this problem is i386. And most compilers on i386 offered a flag like this a looooong time ago.

Date​: Sat\, 22 Jan 2011 14​:25​:23 -0800 From​: Greg Lindahl \greg@&#8203;blekko\.com To​: Chip Salzenberg \rev\.chip@&#8203;gmail\.com Cc​: p5p \perl5\-porters@&#8203;perl\.org Subject​: Re​: Being more careful with FP on gcc​: Message-ID​: \20110122222523\.GB14655@&#8203;bx9\.net

On Sat\, Jan 22\, 2011 at 08​:39​:13AM -0800\, Chip Salzenberg wrote​:

After carefully considering http​://blog.andreas.org/display?id=9 I believe we should add the flag "-fexcess-precision=standard" when compiling on gcc 4.5+. Any controversy here?

That flag is the right thing to do -- I'm surprised that it wasn't noticed earlier. It's not hard to write a little test in C so that we would know if other compilers need a similar switch\, too.

Thank you for the reminder. I meant to look into this\, but life intervened last year\, and I have subsequently forgotten. I have taken this ticket to remind me about it.

If you still have a "little test in C" handy\, I would appreciate it.

For anyone interested​: I would also welcome a pure perl test (to consider including in the test suite) to make sure we succeed in doing whatever it is we are trying to do.

Incidentally\, though gcc has had -ffloat-store for quite some time\, it didn't quite do what we want. Based on the description in the fine manual\, -fexcess-precision=standard looks like it might be a good choice\, but it is only available in gcc-4.5 and later. gcc-4.5.2 was released in December\, 2010\, which means it's not necessarily all that widespread yet.
For example\, Debian stable still uses 4.4.5. Unfortunately\, that's what runs on the system I usually use to work on Configure\, so I have to sort all that out first\, and it's unlikely to be quick.

And\, of course\, even if we do default to using that flag tomorrow\, I predict that the vagaries of floating point are such that we'll still be getting reports of floating point rounding issues for years to come :-).

--   Andy Dougherty doughera@​lafayette.edu

p5pRT commented 11 years ago

From greg@blekko.com

On Fri\, Oct 05\, 2012 at 09​:10​:53AM -0400\, Andy Dougherty wrote​:

If you still have a "little test in C" handy\, I would appreciate it.

This test works for me on my x86-64 desktop\, using -m32 to pretend to be i386. It fools the optimizer by passing a constant in on the command line.

I think what you want to use to fix this\, by the way\, is -mpc64\, which appeared in gcc 4.3\, if I read the release notes correctly. The manpage gives a scary-looking warning about using -mpc64 when linking with mathematical libraries\, which I suppose could be true\, but really\, ever since SSE appeared\, people stopped writing libraries that depended on 80-bit math being available.

Even better would be to stop compiling for the least common denominator and use -march and -mfpmath to force SSE instead of 387 math. After some experimenting I found that this did the trick​:

gcc -O2 -m32 -march=pentium4 -mfpmath=sse test_fp80.c

This is a higher-level decision\, though\, I know most distros supporting i386 are not willing to go quite this far.

Finally\, if you really do want to use -fexcess-precision=standard\, you should also check out -fexcess-precision=fast.

Incidentally\, though gcc has had -ffloat-store for quite some time\, it didn't quite do what we want.

Right\, it inhibits many good optimizations\, you don't want that.

-- greg

/* * this program tests arithmetic to see if there is * excess precision visible in 64-bit floating point * computations. For example\, gcc on i386 targets defaults * to using 80387 80-bit precision math\, and sees * excess precision. gcc on x86-64 defaults to using * SSE math\, and does not see excess precision. * * gcc -O test_fp80.c * ./a.out 3 * */

#include \<stdio.h> #include \<stdlib.h>

int main( int argc\, char **argv ) {   double one = 1.0;   double three;   double constant = 0.3333333333333333333333333;   double residue;   char *garbage;

  if ( argc \< 2 )   {   fprintf( stderr\, "No arg given. Give me a 3!\n" );   exit( 2 );   }

  three = strtod( argv[1]\, &garbage );

  residue = constant - one / three;

  if ( residue > 1.e-17 || residue \< -1.e-17 )   {   printf( "Saw excess precision.\n" );   exit( 1 );   }   else   {   printf( "Did not see excess precision.\n" );   exit( 0 );   } }

p5pRT commented 7 years ago

From @dcollinsn

This is the expected behavior of floats. We have a testcase here for which the closest 80-bit float is below the actual value\, and the closest 64-bit float is above it. Since the testcase is a 'tipping point' for rounding\, this results in slightly different behavior.

This is no different than any other platform difference in floating point. There are values that are exactly representable by 64 bit floats but not by 80 bit floats. Is it a bug that\, for example (x/2)*2==x is true on 32 bit platforms but false on 64 bit platforms for certain values of x?

We can "fix" this by loading a bignum library by default\, or by using the lowest common denominator - 64 bit double precision floats on all platforms? - but either of those options seems more disruptive. We already support using extended precision on platforms where it is available - is -Duselongdouble a bug?

perldoc perldata says\, (in a paragraph with some unrelated discussion on hex fp literals)​:

  Notice that while most current platforms use the 64-bit IEEE 754 floating point\, not all do. Another potential source of (low-order) differences are the floating point rounding modes\, which can differ between CPUs\, operating systems\, and compilers\, and which Perl doesn't control.

perldoc perlnumber says​:

  Perl can internally represent numbers in 3 different ways​: as native integers\, as **native floating point numbers**\, and as decimal strings. Decimal strings may have an exponential notation part\, as in "12.34e-56" . Native here means "a format supported by the C compiler which was used to build perl".

  However\, "native" floats have a most fundamental restriction​: they may represent only those numbers which have a relatively "short" representation when converted to a binary fraction. For example\, 0.9 cannot be represented by a native float\, since the binary fraction for 0.9 is infinite​:   binary0.1110011001100...   with the sequence 1100 repeating again and again. In addition to this limitation\, the exponent of the binary number is also restricted when it is represented as a floating point number. On typical hardware\, floating point values can store numbers with up to 53 binary digits\, and with binary exponents between -1024 and 1024. In decimal representation this is close to 16 decimal digits and decimal exponents in the range of -304..304. The upshot of all this is that Perl cannot store a number like 12345678901234567 as a floating point number on such architectures without loss of information.

perldoc perlop says​:

  Floating-point numbers are only approximations to what a mathematician would call real numbers. There are infinitely more reals than floats\, so some corners must be cut. For example​:   printf "%.20g\n"\, 123456789123456789;   # produces 123456789123456784   Testing for exact floating-point equality or inequality is not a good idea. Here's a (relatively expensive) work-around to compare whether two floating-point numbers are equal to a particular number of decimal places.

perldoc perlop and perlmodlib list some arbitrary precision libraries

I suggest that this ticket be closed rejected\, as Perl's use of native floats is documented\, as are the dangers of expecting a float to be exactly equal to the decimal value used to create it\, and both core and CPAN provide options for those who need arbitrary-precision arithmetic.

-- Respectfully\, Dan Collins

p5pRT commented 7 years ago

From [Unknown Contact. See original ticket]

This is the expected behavior of floats. We have a testcase here for which the closest 80-bit float is below the actual value\, and the closest 64-bit float is above it. Since the testcase is a 'tipping point' for rounding\, this results in slightly different behavior.

This is no different than any other platform difference in floating point. There are values that are exactly representable by 64 bit floats but not by 80 bit floats. Is it a bug that\, for example (x/2)*2==x is true on 32 bit platforms but false on 64 bit platforms for certain values of x?

We can "fix" this by loading a bignum library by default\, or by using the lowest common denominator - 64 bit double precision floats on all platforms? - but either of those options seems more disruptive. We already support using extended precision on platforms where it is available - is -Duselongdouble a bug?

perldoc perldata says\, (in a paragraph with some unrelated discussion on hex fp literals)​:

  Notice that while most current platforms use the 64-bit IEEE 754 floating point\, not all do. Another potential source of (low-order) differences are the floating point rounding modes\, which can differ between CPUs\, operating systems\, and compilers\, and which Perl doesn't control.

perldoc perlnumber says​:

  Perl can internally represent numbers in 3 different ways​: as native integers\, as **native floating point numbers**\, and as decimal strings. Decimal strings may have an exponential notation part\, as in "12.34e-56" . Native here means "a format supported by the C compiler which was used to build perl".

  However\, "native" floats have a most fundamental restriction​: they may represent only those numbers which have a relatively "short" representation when converted to a binary fraction. For example\, 0.9 cannot be represented by a native float\, since the binary fraction for 0.9 is infinite​:   binary0.1110011001100...   with the sequence 1100 repeating again and again. In addition to this limitation\, the exponent of the binary number is also restricted when it is represented as a floating point number. On typical hardware\, floating point values can store numbers with up to 53 binary digits\, and with binary exponents between -1024 and 1024. In decimal representation this is close to 16 decimal digits and decimal exponents in the range of -304..304. The upshot of all this is that Perl cannot store a number like 12345678901234567 as a floating point number on such architectures without loss of information.

perldoc perlop says​:

  Floating-point numbers are only approximations to what a mathematician would call real numbers. There are infinitely more reals than floats\, so some corners must be cut. For example​:   printf "%.20g\n"\, 123456789123456789;   # produces 123456789123456784   Testing for exact floating-point equality or inequality is not a good idea. Here's a (relatively expensive) work-around to compare whether two floating-point numbers are equal to a particular number of decimal places.

perldoc perlop and perlmodlib list some arbitrary precision libraries

I suggest that this ticket be closed rejected\, as Perl's use of native floats is documented\, as are the dangers of expecting a float to be exactly equal to the decimal value used to create it\, and both core and CPAN provide options for those who need arbitrary-precision arithmetic.

-- Respectfully\, Dan Collins

p5pRT commented 7 years ago

@iabyn - Status changed from 'open' to 'rejected'