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

cheers brothers and sisters,

I have this sub to calculate the 3 most significant bits based on an integer. The integer I get is the integer value of the TOS byte, a value which is retreived over SNMP. I have to find the TOS Precedence, and that is the sum of the 3 MSBs.

The sub I have works, but laziness seems to strike everyone eventually, I was wondering if there are easier or better ways to do it? I'm just always curious about how someone else would do it ;-)

the code:
sub calc_tosprecedence { my $int_val = shift; my $bit = 7; my @b = (0,0,0,0,0,0,0,0); while ($int_val > 0 ) { $rest = 1 if $int_val - 2**$bit >= 0 ; $rest = 0 if $int_val - 2**$bit < 0 ; $int_val = $int_val - 2**$bit if $rest; $b[$bit-- ] = $rest; } @b = reverse @b; my @prec = @b[0 .. 2]; $sum = 0; @prec = reverse @prec; $sum += $prec[$_] * 2**$_ for (0 .. $#prec); return $sum }
The code basically:
  • gets an integer as argument
  • converts it to a binary
  • takes the 3 last (MSB) bits from it as a binary
  • calculates the integer value of that binary
  • Thanks..

    --
    to ask a question is a moment of shame
    to remain ignorant is a lifelong shame

    Replies are listed 'Best First'.
    Re: calculating the 3 MSBs from an integer
    by borisz (Canon) on Feb 17, 2005 at 13:00 UTC
      Here is some code, that does the same as yours.
      sub calc_tosprecedence{ use integer; return ( $_[0] & 0xff ) >> 5; }
      Boris

        I think I have understood this correctly but please put me right if I am barking up the wrong tree

        $_[0] & 0xff # A bitmask to gets the last (8 bit) byte from the intege +r. # It has exactly the same result as $_[0] % 256 >> 5 # bitshift the result of the above so all but # the 3 MSB drop off the end.
        the return automagically maps this to the decimal for the three remaining bits. Was use integer necessary for this or does it improve efficiency ?

        Here is a one liner to dump what is going on

        perl -le'print join "\t", $_, (unpack "B*", pack "I*", $_),($_ & 0xFF) + >> 5 for (0..256)'
        and some of the output for the interesting regions
        0 00000000000000000000000000000000 0 1 00000000000000000000000000000001 0 2 00000000000000000000000000000010 0 . . 30 00000000000000000000000000011110 0 31 00000000000000000000000000011111 0 32 00000000000000000000000000100000 1 33 00000000000000000000000000100001 1 . . 222 00000000000000000000000011011110 6 223 00000000000000000000000011011111 6 224 00000000000000000000000011100000 7 225 00000000000000000000000011100001 7 . . 255 00000000000000000000000011111111 7 256 00000000000000000000000100000000 0

        Cheers,
        R.

        Pereant, qui ante nos nostra dixerunt!
          You are right on everything. use integer is not needed, I do it always since shifts are done sign wo integer and unsigned with use integer. In this case it does not matter.
          Boris
          thanks for the explanation, but my output is like this:
          0 00000000000000000000000000000000 0 1 00000001000000000000000000000000 0 2 00000010000000000000000000000000 0 3 00000011000000000000000000000000 0 ..

          the binary forms are "a bit" akward, no? I just copy pasted your command line..

          and why is the piece: $_ & 0xFF needed? without it, the code seems to work as well... or am i missing something mayor overhere?

          anyhow.. now i know i shouldn't have skipped the chapters about bitwise operators :-D

          --
          to ask a question is a moment of shame
          to remain ignorant is a lifelong shame

        wow... dr00l ... and thanx a bunch!!! this is truely superlazy... thanks for the insights
        --
        to ask a question is a moment of shame
        to remain ignorant is a lifelong shame
    Re: calculating the 3 MSBs from an integer
    by spurperl (Priest) on Feb 18, 2005 at 10:26 UTC
      In general, it may be useful to know what "MSB" means, because it depends on the machine. The following should be a simple and portable method of converting any unsigned integer to its binary representation:

      sub dec2bin { return sprintf("%b", $_[0]); }
        yeah true... but it seems the bitshifting works correctly on whatever OS, so it's just the visual representation that can be a bit akward... but that was not a requirement ;-)

        thanks for the info..

        --
        to ask a question is a moment of shame
        to remain ignorant is a lifelong shame