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

Hi PerlMonks.. =)
I have a 4 byte hex string and I want to get a decimal number out of it that is bit packed N bits long and at M bits offset.

For example...
Hex : 1c023d64

Assume the left is the MSB and right is the LSB (bits 1->32).
I want to compose a decimal number using bits 23-27 so thats N = 23 and M = 5.
So if I convert the above hex to binary...
Bin : 000111000000001000111101011001100

now the bit sequence i want is...
01011 and then convert this to decimal would give decimal number 11. Now whats the nicest way to do this automatically? My string manipulation skills are less than 1337 so I was doing this a rather painful way...
sub Hex2Bin { $hex = $_[0]; %h2b = ( 0 => "0000", 1 => "0001", 2 => "0010", 3 => "0011", 4 => "0100", 5 => "0101", 6 => "0110", 7 => "0111", + 8 => "1000", 9 => "1001", a => "1010", b => "1011", c => "1100", d => "1101", e => "1110", f => "1111"); (my $binary = $hex) =~ s/(.)/$h2b{lc $1}/g; return $binary; }

This would convert the hex to a binary string and from there I was going to extract the bits and then recompose the binary.
I'm sure there is some slick commands around that will let me do this quickly...? Any help would be appreciated.
For the curious I'm trying to pull out channel status information that's bit packed for GPS satellite logs I'm playing with.

Regards Paul.

Replies are listed 'Best First'.
Re: Hex/binary/Decimal
by saintmike (Vicar) on Feb 11, 2005 at 23:15 UTC
    Bit shifting and bitwise and:
    my $hex = hex("1c023d64"); my $mask = 31 << 5; my $result = ($hex & $mask) >> 5; printf "Hex: %30b\n", $hex; printf "Mask: %30b\n", $mask; printf "Result: %30b (%d)\n", $result, $result;
    shows the result like this:
    Hex: 11100000000100011110101100100 Mask: 1111100000 Result: 1011 (11)

      Saintmike,
      Thankyou =, exactly what I need, I haven't done bit twiddling in perl before. So simple.....

      Warm Regards Paul.
Re: Hex/binary/Decimal
by trammell (Priest) on Feb 11, 2005 at 23:18 UTC
    The following code gives the desired result for your input:
    sub hexstring2num { my $n = hex($_[0]); return ($n >> 5) & 0x1f; }