Front page | perl.perl5.porters |
Postings from May 2008
[perl #53784] 64-bit Integers -- inexact division gives odd result when is large
Thread Next
From:
Chris Hall
Date:
May 7, 2008 03:11
Subject:
[perl #53784] 64-bit Integers -- inexact division gives odd result when is large
Message ID:
rt-3.6.HEAD-20841-1210096730-1968.53784-75-0@perl.org
# New Ticket Created by Chris Hall
# Please include the string: [perl #53784]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=53784 >
This is a bug report for perl from chris.hall@highwayman.com,
generated with the help of perlbug 1.35 running under perl v5.8.8.
-----------------------------------------------------------------
[Please enter your report here]
Division of a large 64-bit integer by a small integer gives peculiar
(broken) result when the division is inexact.
Consider:
idiv(0x0FED_CBA9_8765_4321, 9, 9) ;
print "_" x 70, "\n" ;
idiv(1<<52, 3, 2) ;
sub idiv {
my ($z, $j, $b) = @_ ;
printf "a = 0x%016X * $b + i, for i = 0..%d\n", $z, $j ;
print " i: d = int(a/$b) : a/$b :",
" a%$b : a - d*$b\n" ;
foreach my $i (0..$j) {
my $a = ($z * $b) + $i ;
my $q = $a / $b ;
my $d = int($q) ;
my $r = $a % $b ;
my $s = $a - ($d * $b) ;
printf " %2d: 0x%016X : %20s : %+3d : %+5d\n", $i, $d, "$q", $r, $s ;
} ;
} ;
which on an x86-64 produces:
a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9
i: d = int(a/9) : a/9 : a%9 : a - d*9
0: 0x0FEDCBA987654321 : 1147797409030816545 : +0 : +0
1: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +1 : -854
2: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +2 : -853
3: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +3 : -852
4: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +4 : -851
5: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +5 : -850
6: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +6 : -849
7: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +7 : -848
8: 0x0FEDCBA987654380 : 1.14779740903082e+18 : +8 : -847
9: 0x0FEDCBA987654322 : 1147797409030816546 : +0 : +0
______________________________________________________________________
a = 0x0010000000000000 * 2 + i, for i = 0..3
i: d = int(a/2) : a/2 : a%2 : a - d*2
0: 0x0010000000000000 : 4503599627370496 : +0 : +0
1: 0x0010000000000000 : 4503599627370496 : +1 : +1
2: 0x0010000000000001 : 4503599627370497 : +0 : +0
3: 0x0010000000000002 : 4503599627370498 : +1 : -1
The first section shows the effect. Where the integer division is exact we
get the right integer result. Where it is not exact, the result is floated,
with hopeless loss of significance !
I assume that the code runs an integer division, and when the remainder is
not zero it floats the result of the division and then adds
remainder / divisor.
The second section shows what happens when the result of the division is
53 bits of integer (same as precision of the floating point), plus fraction
when the result is not exact. Note the effect of Round-to-Even !
I suggest that the code should be extended to check if the result is
>= max integer in floating form. If it is, then the result should be left
in integer form, and: if remainder is > divisor/2 round up, or
if remainder == divisor/2, round to even.
(As shown above, the % operator is giving the right result. So all is
not lost.)
[FWIW: Round-to-Even is all very well, but in this case truncation would
seem a better choice -- all inexact integer divisions would then
always yield the integer result + fraction (when precision allows).]
[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
category=core
severity=high
---
This perlbug was built using Perl v5.8.8 in the Red Hat build system.
It is being executed now by Perl v5.8.8 - Thu Mar 20 04:50:07 EDT 2008.
Site configuration information for perl v5.8.8:
Configured by Red Hat, Inc. at Thu Mar 20 04:50:07 EDT 2008.
Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
Platform:
osname=linux, osvers=2.6.18-53.1.6.el5xen, archname=x86_64-linux-thread-multi
uname='linux xenbuilder2.fedora.redhat.com 2.6.18-53.1.6.el5xen #1 smp wed jan 16 04:10:44 est 2008 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 -Dversion=5.8.8 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -
Dprefix=/usr -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64 -Dprivlib=/usr/lib/perl5/5.8.8 -Dsitelib=/usr/lib/perl5/site_perl/5.8.8 -Dvendorlib=/us
r/lib/perl5/vendor_perl/5.8.8 -Darchlib=/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi -Dsitearch=/usr/lib64/perl5/site_perl/5.8.8/x86_64-linu
x-thread-multi -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi -Darchname=x86_64-linux -Dvendorprefix=/usr -
Dsiteprefix=/usr -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 -
Dinc_version_list=5.8.7 5.8.6 5.8.5 -Dscriptdir=/usr/bin'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef 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 -Wdeclaration-after-statement -I/usr/local/include -
D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
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 -Wdeclaration-after-statement -I/usr/local/include -I/usr/include/gdbm'
ccversion='', gccversion='4.1.2 20070925 (Red Hat 4.1.2-33)', 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 =''
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.7'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/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 v5.8.8:
/usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.8.7/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.8.6/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.8.5/x86_64-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.8
/usr/lib/perl5/site_perl/5.8.7
/usr/lib/perl5/site_perl/5.8.6
/usr/lib/perl5/site_perl/5.8.5
/usr/lib/perl5/site_perl
/usr/lib64/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.8.7/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.8.6/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.8.5/x86_64-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.8
/usr/lib/perl5/vendor_perl/5.8.7
/usr/lib/perl5/vendor_perl/5.8.6
/usr/lib/perl5/vendor_perl/5.8.5
/usr/lib/perl5/vendor_perl
/usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi
/usr/lib/perl5/5.8.8
.
---
Environment for perl v5.8.8:
HOME=/home/GMCH
LANG=en_GB.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PERL_BADLANG (unset)
SHELL=/bin/bash
--
Chris Hall highwayman.com
Thread Next
-
[perl #53784] 64-bit Integers -- inexact division gives odd result when is large
by Chris Hall