Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Bitwise Operator Error

by ravishi (Acolyte)
on Oct 02, 2008 at 18:26 UTC ( #715064=perlquestion: print w/ replies, xml ) Need Help??
ravishi has asked for the wisdom of the Perl Monks concerning the following question:

I am using Perl and I have a string such as the $testString below. I take the string and remove the trailing/leading whitespace. Then, I remove the spaces between the words. My last goal is to do a bitwise & operator (mask) to determine if the 2nd bit is a 1.

What I want in this example is an end output of 0. I get 4294967295 with an error saying "Argument "00008008000000FF00800000" isn't numeric in bitwise and (&) at .... line 16. Do I have to typecast the array to be an int? I thought you didn't have to do that. Please advise.

#!/usr/bin/perl -w # File displayPipeTracer2.pl $testString = " 00008008 000000FF 00800000"; print "Original: $testString\n"; $testString =~ s/^\s+//; #remove leading spaces $testString =~ s/\s+$//; #remove trailing spaces print "Removed L/T: $testString\n"; $testString =~ s/\s//g; print "Removed ws: $testString\n"; $maskResult = $testString & 400000000000000000000000; print "Mask Result: $maskResult\n";

Comment on Bitwise Operator Error
Download Code
Replies are listed 'Oldest First'.
Re: Bitwise Operator Error
by broomduster (Priest) on Oct 02, 2008 at 18:49 UTC
    Your hexadecimal number in $testString needs to begin with 0x be properly interpreted as hexadecimal. Then it will work. You can also simplify your white-space removal. All together, here is one way to get where you want to go:
    $testString =~ s/\s+//g;
    $testString =~ s/^/0x/; $maskResult = $testString & 400000000000000000000000;
    $maskResult = hex( $testString ) & 0x400000000000000000000000;

    Updated: Need to use hex and need to have mask as hex string.

    Updated 2: I see ikegami has also pointed out my error(s) corrected above.

    Updated 3: and ikegami has also noted the need for Math::BigInt here.

      Thanks for the help but I just tried what you suggested and it doesn't seem to work. It outputs a 0 which is correct but I get a warning saying that it isn't numeric. I then changed the first bit of the original string to an F to test if I get an output of 1, and I still get a 0.

      That's wrong.

      >perl -we"print 0+'0x0001'" Argument "0x0001" isn't numeric in addition (+) at -e line 1. 0

      See my reply to the OP for details

Re: Bitwise Operator Error
by ikegami (Pope) on Oct 02, 2008 at 19:13 UTC

    Strings used in numerical context as treated as decimal numbers. Use hex to convert them

    Similarly, numerical literals are treated as decimal numbers. Prepend 0x.

    #!/usr/bin/perl -w # File displayPipeTracer2.pl my $testString = " 00008008 000000FF 00800000"; $testString =~ s/\s+//g; my $maskResult = hex($testString) & 0x400000000000000000000000; print "Mask Result: $maskResult\n";

    But those numbers are huge!

    Integer overflow in hexadecimal number at script.pl line 7. Hexadecimal number > 0xffffffff non-portable at script.pl line 7. Integer overflow in hexadecimal number at script.pl line 7. Hexadecimal number > 0xffffffff non-portable at script.pl line 7. Mask Result: 4294967295

    But Perl is capable of large number arithmetic using bigint/Math::BigInt.

    #!/usr/bin/perl -w # File displayPipeTracer2.pl use bigint; my $testString = " 00008008 000000FF 00800000"; $testString =~ s/\s+//g; $testString = Math::BigInt->new("0x$testString"); my $maskResult = $testString & 0x400000000000000000000000; print "Mask Result: $maskResult\n";
      Thanks, that worked. However, this is just a sample code. I tried using bigint in my main program and it gives me a whole slew of new errors. It is a GUI program using Tk and a few Tk modules (Tk::TableMatrix, Tk::Balloon, Tk::Bitmap, and Tk::Pane). I'm guessing that bigint and the Tk modules conflict. These are two separate errors I get when I run it with bigint. The second I get when I comment out the first error.
      C:\code>DisplayPipeTracer15.pl -trace out.PipeTracer.xml '8┬├⌐☻♥' isn't numeric at C:/Perl/site/ +lib/Tk/Widget.pm line 205. at C:\code\displayPipeTracer15.pl line 387 C:\code>DisplayPipeTracer15.pl -trace out.PipeTracer.xml trace_file = out.PipeTracer.xml Ports to be Analyzed: 1 2 'h┬├⌐☻♥' isn't numeric at C:/Perl/site/ +lib/Tk.pm line 250. at C:\code\displayPipeTracer15.pl line 159
      Here is my code for the lines the errors point to. First is 387 and the second is 159.

      Line 387:

      my $cycleAccept = $statusBar->Button(-text => "Go to", -font => ['Arial', 8], -command=> \&GoToCycle, -bd => 1, -takefocus => 'never', -highlightthickness => 0)->pack( +-side => 'left');

      Line 159:

      $PortFrame = $allPortsFrame->Scrolled('TableMatrix', -resizeborders=>'none', -titlerows => 1, -titlecols => 1, -background => 'white', -foreground => 'white', -borderwidth => 0, -rows => 6, -colstretchmode=>'all', -cols => 1, -colwidth => 25, -cache => 1, -scrollbars => "osoe")->pa +ckAdjust(-side => "top", + -fill => 'both', + -expand => 1);
        bigint basically turns every number into an object which acts as a number. Limit the scope of bigint using curlies, or create the objects yourself were needed.
        #!/usr/bin/perl -w # File displayPipeTracer2.pl { # Only makes objects from numbers in these curlies use bigint; my $testString = " 00008008 000000FF 00800000"; $testString =~ s/\s+//g; $testString = Math::BigInt->new("0x$testString"); my $maskResult = $testString & 0x400000000000000000000000; print "Mask Result: $maskResult\n"; }
        #!/usr/bin/perl -w # File displayPipeTracer2.pl my $testString = " 00008008 000000FF 00800000"; $testString =~ s/\s+//g; $testString = Math::BigInt->new("0x$testString"); my $mask = Math::BigInt->new('0x400000000000000000000000'); my $maskResult = $testString & $mask; print "Mask Result: $maskResult\n";
Re: Bitwise Operator Error
by jethro (Monsignor) on Oct 02, 2008 at 19:21 UTC

    Even if you follow broomdusters advice, you still have a big problem. The internal numbers presentation automatically changes a number to floating point if it gets too big. Anding floating point numbers is quite useless as you can see here:

    $maskResult = 4000000000000000 & 4000000000000000; print $maskResult,"\n"; ####prints 4294967295 $maskResult = 1000000000000000 & 4000000000000000; print $maskResult,"\n"; ####prints 4294967295

    If you want to use really large integers you need bigint or Math:BigInt

Re: Bitwise Operator Error
by XooR (Beadle) on Oct 02, 2008 at 19:29 UTC
    I reimplemented your example with BigInt. I hope that this you wanted:
    #!/usr/bin/perl # File displayPipeTracer2.pl use warnings; use strict; use Math::BigInt; my $testString = " 00008008 000000FF 00800000"; print "Original: $testString\n"; $testString =~ s/\s//g; $testString =~ s/^/0x/g; my $big_x = new Math::BigInt($testString); my $big_y = new Math::BigInt("40000000_00000000_00000000"); my $big_result = $big_x->band( $big_y ); print $big_x->as_hex(), " & ", $big_y->as_hex(), "\n"; print "Mask Result: ", $big_result->as_hex(), "\n";
Re: Bitwise Operator Error
by almut (Canon) on Oct 02, 2008 at 21:46 UTC

    You could also avoid going numeric altogether by converting your string to a bitstring (a string of ASCII 0's and 1's, that is, here):

    my $testString = " 00008008 000000FF 00800000"; $testString =~ s/\s+//g; # convert to a string representation of '0's and '1's my $bits = unpack("B*", pack("H*", $testString)); # test if specific bit is set my $maskResult = substr($bits, 1, 1) eq '1'; printf "%s\n--> 2nd bit from left: %d\n", $bits, $maskResult;

    Checking for several non-adjacent bits with substr might get a bit unwieldy (if you need that) ... in which case you could use the bitwise string-AND operation. For example

    my $testString = " 01008008 000000DF 00800000"; my $mask = "42000000 00000020 00000000"; for ($testString, $mask) { s/\s+//g; $_ = pack("H*", $_); # convert from hex to (binary) bitstring } # bitwise string AND my $maskResult = $testString & $mask; # ----- visualise what's going on (functionally not required) ----- for my $bits ($testString, $mask, '', $maskResult) { if ($bits) { print unpack("B*", $bits), "\n"; } else { print "-" x 96, "\n"; } } # --------------------------------------------------------------- # check for any non-zero bytes $maskResult =~ tr/\0//d; printf "There were %s matching bits.\n", length($maskResult) ? "some": +"no";

    This would test whether any of the bits specified in $mask are set in $testString.

    There is always more than one way to do it :)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://715064]
Approved by eff_i_g
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (11)
As of 2015-07-07 16:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (92 votes), past polls