syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
Using a recent installation of Cygwin (which comes with a "use64bitint" version of perl 5.8.7) I find the following:
Rob@desktop ~/pscrpt $ cat try.pl use warnings; $x = 2 ** 54 + 123; # 18014398509482107 $y = 2 ** 54 + 125; # 18014398509482109 if($x + 2 == $y) {print "fine\n"} else {print "crap\n"} if($x == $y) {print "crap\n"} else {print "fine\n"} Rob@desktop ~/pscrpt $ perl try.pl crap crap
Now that output doesn't quite coincide with what I expected from a perl that claims to have been built with "use64bitint".

Is there something else I'm overlooking ? ... or am I just being plain unreasonable ? The full output of 'perl -V' appears below my sig.

Cheers,
Rob
$ perl -V Summary of my perl5 (revision 5 version 8 subversion 7) configuration: Platform: osname=cygwin, osvers=1.5.18(0.13242), archname=cygwin-thread-mult +i-64int uname='cygwin_nt-5.1 inspiron 1.5.18(0.13242) 2005-07-02 20:30 i68 +6 unknown unknown cygwin ' config_args='-de -Dmksymlinks -Duse64bitint -Dusethreads -Uusemyma +lloc -Doptimize=-O3 -Dman3ext=3pm -Dusesitecustomize' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemulti +plicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=define use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -p +ipe -I/usr/local/include', optimize='-O3', cppflags='-DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -pipe -I/usr +/local/inc lude' ccversion='', gccversion='3.4.4 (cygming special) (gdc 0.12, using + dmd 0.125)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='of +f_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='ld2', ldflags =' -s -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -ldb -lcrypt -lgdbm_compat perllibs=-lcrypt -lgdbm_compat libc=/usr/lib/libc.a, so=dll, useshrplib=true, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' -s' cccdlflags=' ', lddlflags=' -s -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY USE_ITHREADS USE_64_BIT_INT USE_LARGE_FILES USE_SITECUSTOMIZE PERL_IMPLICIT_CONTEXT Locally applied patches: SPRINTF0 - fixes for sprintf formatting issues - CVE-2005-3962 Built under cygwin Compiled at Dec 30 2005 02:44:25 %ENV: CYGWIN="" @INC: /usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8 /usr/lib/perl5/site_perl/5.8/cygwin /usr/lib/perl5/site_perl/5.8 /usr/lib/perl5/site_perl/5.8/cygwin /usr/lib/perl5/site_perl/5.8 /usr/lib/perl5/vendor_perl/5.8/cygwin /usr/lib/perl5/vendor_perl/5.8 /usr/lib/perl5/vendor_perl/5.8/cygwin /usr/lib/perl5/vendor_perl/5.8 .

Replies are listed 'Best First'.
Re: -Duse64bitint and (Cygwin) perl 5.8.7 (it's not how many bits, but how you use them)
by tye (Sage) on Nov 30, 2006 at 07:15 UTC

    It can get tricky when you have the situation where your "int"s can hold more significant bits than your "double"s, but, of course, your doubles can deal with larger and smaller exponents than your ints. So, when you have two Perl numeric values to do an operation with, should you perform the operation as ints or as doubles?

    Before 64-bit ints, the decision was simple; you do all math as doubles because the doubles can do everything the ints can do.

    To counter your example, consider:

    $x = 2 ** 45 + 1; $y = 2 ** 45 + 1.5; if($x + .5 == $y) {print "fine\n"} else {print "crap\n"} if($x == $y) {print "crap\n"} else {print "fine\n"} # Then $x = 1e55 + 1e44; $y = 1e55 + 2e44; # ...

    Is Perl smart enough to tell that it needs to do your example with 64-bit ints but that it needs to do my examples with doubles? Obviously not. Can it be made that smart? Perhaps, but it might not be easy.

    You could perlbug this to give the maintainers something to think about. But I hope you have a better appreciation for the difficultly here.

    Note that you can help Perl know what you want here with a simple use integer;.

    - tye        

      use integer

      That's the piece I was overlooking. I was expecting that, as with purely 32-bit arithmetic, the number would be an IV unless it was either a fraction, or was too big to fit into an IV. But that's not the case - an integer becomes an NV as soon as 53 bits are exceeded (even though the IV can accommodate 64 bits). Of course, with 'use integer;', the integer retains it's IV status, even when it exceeds 64 bits.

      Things start to make some sense ... though still appear a little buggy. (But maybe that's just because I need to readjust my vision :-)

      Cheers,
      Rob
      Is "use bignum;" an option? --->
      use bignum;
      use warnings;
      
      $x = 2**54 + 123; # 18014398509482107
      $y = 2**54 + 125; # 18014398509482109
      
      if($x + 2 == $y) {print "fine\n"}
      else {print "crap\n"}
      
      if($x == $y) {print "crap\n"}
      else {print "fine\n"}
      
      --->
      fine
      fine