Reputation: 3360
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
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:
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