Perl-Sensitive Sunglasses PerlMonks

### Re^2: How to convert binary to hexadecimal

 on Jun 14, 2009 at 09:04 UTC ( #771369=note: print w/replies, xml ) Need Help??

this function works only for 32 bits, this will work for any binary length sub b2h { my \$num=shift; my \$WIDTH=32; my \$index=length(\$num)-\$WIDTH; print "index= \$index\n"; my \$hex=""; do { my \$width=\$WIDTH; if (\$index<0) { \$width+=\$index; \$index=0; } \$cut_string=substr(\$num,\$index,\$width); print "index is \$index width is \$width Cut String is \$cut_string\n"; \$hex= sprintf('%X', oct("0b\$cut_string")). \$hex; \$index-=\$WIDTH; } while (\$index>(-1*\$WIDTH)); return \$hex; }
• Comment on Re^2: How to convert binary to hexadecimal

Replies are listed 'Best First'.
Re^3: How to convert binary to hexadecimal
by toolic (Bishop) on Oct 04, 2012 at 13:56 UTC
Since the code Does What I Want (works even for bit widths > 32), I have made it readable by using perltidy. I have also made it strict and removed the print statements:
```use warnings FATAL => 'all';
use strict;

for (
qw(
00
1010
1110
010001
01101011
),
'1' x 33,
'0101' x 16
) {
my \$h = b2h(\$_);
print "\$_ \$h width=", length(\$_), "\n";
}
exit;

sub b2h {
my \$num   = shift;
my \$WIDTH = 32;
my \$index = length(\$num) - \$WIDTH;
my \$hex = '';
do {
my \$width = \$WIDTH;
if (\$index < 0) {
\$width += \$index;
\$index = 0;
}
my \$cut_string = substr(\$num, \$index, \$width);
\$hex = sprintf('%X', oct("0b\$cut_string")) . \$hex;
\$index -= \$WIDTH;
} while (\$index > (-1 * \$WIDTH));
return \$hex;
}

__END__

Output:

00 0 width=2
1010 A width=4
1110 E width=4
010001 11 width=6
01101011 6B width=8
111111111111111111111111111111111 1FFFFFFFF width=33
0101010101010101010101010101010101010101010101010101010101010101 55555
+55555555555 width=64

I have also been attempting to implement this with pack and unpack, to no avail.

Here's another way to do it.

```use warnings;
use strict;

foreach (
qw(
00
1010
1110
010001
01101011
),
'1' x 33,
'0101' x 16
) {
my \$h2 = b2h2(\$_);
\$h2 =~ s/(\w{4})\B/\$1 /g;
print "\$_ \$h2 width=", length(\$_), "\n\n";
}

sub b2h2 {
my \$bin = shift;
my \$extra_characters = length(\$bin)%16;
\$bin = '0' x (16-\$extra_characters) . \$bin if \$extra_characters;
\$bin =~ s/([01]{4})/sprintf "%X", oct("0b\$1")/eg;
return \$bin;
}

__END__

Output:
00 0000 width=2

1010 000A width=4

1110 000E width=4

010001 0011 width=6

01101011 006B width=8

111111111111111111111111111111111 0001 FFFF FFFF width=33

0101010101010101010101010101010101010101010101010101010101010101 5555
+5555 5555 5555 width=64

Here is a way to convert without padding with zeros on the left side. Reverse the binary string and convert groups of four bits then reverse the final string.

```sub b2h {
my \$revbin = reverse shift;
\$revbin =~ s/([01]{1,4})/sprintf "%X", oct('0b' . reverse \$1)/eg;
return reverse \$revbin;
}
hi, I wanted to convert a long binary string to a hexadecimal string. sprintf didn't work because the number was more than 32 bits and thr pack/unpack functions are very complicated for me to understand. hence, I converted it using a truth table. The code is
```sub Bin2Hex{
my %truth_table = (
'0000' => '0' ,
'0001' => '1' ,
'0010' => '2' ,
'0011' => '3' ,
'0100' => '4' ,
'0101' => '5' ,
'0110' => '6' ,
'0111' => '7' ,
'1000' => '8' ,
'1001' => '9' ,
'1010' => 'A' ,
'1011' => 'B' ,
'1100' => 'C' ,
'1101' => 'D' ,
'1110' => 'E' ,
'1111' => 'F' ,
);

my \$count = 0;
my \$hex_string = '';
my \$len = \$#_ ;
#print "len \$len" ;
my \$nibble = '' ;
my \$abit ;
my \$hex_len ;
my \$hex_nibble ;
\$hex_len = ceil(\$len/4)  ;
#print "hex len \$hex_len \n" ;
for(my \$i=0; \$i < \$hex_len ; \$i++) {
for(my \$j= 0 ; \$j < 4; \$j++){
\$abit = pop(@_) ;
if (defined \$abit) {
\$nibble = \$abit.\$nibble;
}
else {
\$nibble = '0'.\$nibble ;

}
}
\$hex_nibble = \$truth_table{\$nibble} ;
\$hex_string = \$hex_nibble.\$hex_string ;
\$nibble = '' ;
}
#print "the converted hex : \$hex_string" ;
return \$hex_string ;
}
the input to the function is binary string stored in list.

Here's another way to do it:

```\$ cat bin2hex.pl
#!/usr/bin/perl
use strict; use warnings;

for my \$b (qw(101101110101001010010100101000101011101010101010101010
1  10 101 1010 10101 101010 11010011 000000000000001 000
+1111
11111 11000011
)) {
print "\$b --> ", bin2hex(\$b), "\n";
}

sub bin2hex {
my \$bin = shift;

# Make input bit string a multiple of 4
\$bin = substr("0000",length(\$bin)%4) . \$bin if length(\$bin)%4;

my (\$hex, \$nybble) = ("");
while (length(\$bin)) {
(\$nybble,\$bin) = (substr(\$bin,0,4), substr(\$bin,4));
\$nybble = eval "0b\$nybble";
\$hex .= substr("0123456789ABCDEF", \$nybble, 1);
}
return \$hex;
}

\$ perl bin2hex.pl
101101110101001010010100101000101011101010101010101010 --> 2DD4A528AEA
+AAA
1 --> 1
10 --> 2
101 --> 5
1010 --> A
10101 --> 15
101010 --> 2A
11010011 --> D3
000000000000001 --> 0001
0001111 --> 0F
11111 --> 1F
11000011 --> C3

It uses an old[1] trick: Since each "nybble"[2] represents a decimal value from 0 to 15, you can build a 16 character string of digits, and use the nybble value as the index of a character.

Then, to simplify things, we ensure that the string is a multiple of four characters long. That way, we simply chop off four characters, turn it into a hex digit, repeating until the string is consumed.

Notes:

[1] How old? It was old when I learned it, roughly 35 years ago.

[2] Four bits == half a byte, thus, a nybble.

...roboticus

When your only tool is a hammer, all problems look like your thumb.

Create A New User
Node Status?
node history
Node Type: note [id://771369]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2018-06-19 21:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should cpanminus be part of the standard Perl release?

Results (115 votes). Check out past polls.

Notices?