Kamrul Khan
Kamrul Khan

Reputation: 3360

Perl: Separate the MSB and rest of the bits from a hex

I need to separate the MSB and the rest of the bits from a hex string. So for example: I have a hex string a2, which is equivalent to 1010 0010. I want to separate out the MSB (1 in this case), and rest of the number convert to decimal. I think I can do something like this:

$hex = 'a2';
$dec = hex($hex);
$bin = sprintf("%b", $dec);
$msb = substr $bin, 0, 1;
$rest = substr $bin 1, 7;

$restDec = oct("0b" . $rest);

However, I do not like using strings for bit operations. Is there a better way of doing this?

Upvotes: 3

Views: 1108

Answers (1)

Jim Garrison
Jim Garrison

Reputation: 86774

Trivial using bitwise operators:

$msb  = ($dec & 128) >> 7
$rest = ($dec & 127)

Explanation:

Decimal 128 is 0x80 or 0b1000_0000, so using the bitwise "and" operator with 128 masks (sets to zero) all but the top bit, which we then shift down to the LSB where the result ends up being 0 or 1. In actuality you could dispense with the masking operation and just shift right but explicitly masking has two advantages:

  1. It makes the intent crystal clear, and
  2. works even if you inadvertently apply this to a number larger than 255.

Decimal 127 is 0x7F or 0b0111_1111 and bitwise "and-ing" this with $dec sets the MSB to zero while leaving alone the rest of the bits.

Additional note: Perl has hexadecimal numeric literals (0x...) and binary literals (0b...), so the above could also be written

$msb  = ($dec & 0x80) >> 7
$rest = ($dec & 0x7F)

Or even

$msb  = ($dec & 0b10000000) >> 7
$rest = ($dec & 0b01111111)

Upvotes: 6

Related Questions