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

Hello,
Using the bitwise & operator to mask numeric values I came across some strange behavior.

4294967296 & 4294967295 = 4294967295

instead of the expected 0.

Can anyone provide an explanation? I'm a tad confused. Thanks.

Replies are listed 'Best First'.
(jeffa) Re: Bitwise & with large numbers
by jeffa (Bishop) on Apr 03, 2002 at 02:47 UTC
    meditate on the output of this: :)
    use strict; for (0..20,) { $a = dec2bin($_+1); $b = dec2bin($_); print "$a = ", $_ + 1, "\n", "$b = ", $_, "\n", "--------\n", dec2bin(($_+1) & $_), " = ", (($_+1) & $_), "\n\n"; } # Perl Cookbook recipe 2.4. sub dec2bin { my $s = unpack("B32", pack("N",shift)); #$s =~ s/^0+(?=\d)//; $s = substr($s,-8,8); return $s; }
    UPDATE: thanks tachyon!

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
    -->

      Actually Anonymonk has a valid point as this is a buffer overflow type bug. 4294967296 is a 33 bit integer, which is of course one bit more than 32. Perhaps you should meditate on this:

      print "2**32 is: ", 2**32, "\n"; print <<TEXT; This is what we should have: 100000000000000000000000000000000 = 4294967296 011111111111111111111111111111111 = 4294967295 ---------------------------------------------- 000000000000000000000000000000000 = 0 But we get a buffer overflow like so, resulting in erroneous output: TEXT for (4294967295) { $a = dec2bin($_+1); $b = dec2bin($_); print "$a = ", $_ + 1, "\n", "$b = ", $_, "\n", "--------\n", dec2bin(($_+1) & $_), " = ", (($_+1) & $_), "\n\n"; } sub dec2bin { return unpack("B*", pack("N",shift)); }

      I have no call for it personally but Math::BigInt might be useful.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Bitwise & with large numbers
by rinceWind (Monsignor) on Apr 03, 2002 at 15:26 UTC
    Using Devel::Peek to look further into what is going on is more revealing:
    #!/usr/local/bin/perl
    
    use strict;
    
    use Devel::Peek;
    
    my $a = 4294967296;
    my $b = 4294967295;
    my $c = $a & $b;
    
    print '$a:';Dump($a);
    print '$b:';Dump($b);
    print '$c:';Dump($c);
    
    
    Results:
    $a:SV = PVNV(0x1abe608) at 0x1ab30a0
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK,IsUV)
      UV = 4294967295
      NV = 4294967296
      PV = 0
    $b:SV = IV(0x1ab2420) at 0x1ab3058
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,IOK,pIOK,IsUV)
      UV = 4294967295
    $c:SV = IV(0x1ab2428) at 0x1ab3088
      REFCNT = 1
      FLAGS = (PADBUSY,PADMY,IOK,pIOK,IsUV)
      UV = 4294967295
    
    
    4294967296 has overflowed the integers on the platform I am using, and is appearing as 0xFFFFFFFF.

    Whether this is expected behaviour or not is maybe upto Larry or p5p.

Re: Bitwise & with large numbers
by dcd (Scribe) on Apr 04, 2002 at 02:08 UTC
    Others have given explanation, but I thought that I'd add that Math::BigInt will give the answer that you desire
    perl -MMath::BigInt -le ' $i=new Math::BigInt "4294967296"; $j=new Math::BigInt "4294967295"; print $i->as_hex(); print $j->as_hex(); print $i->band($j)->as_hex()'
    0x100000000 0xffffffff 0x0