Recipe 2.15 Converting Binary, Octal, and Hexadecimal Numbers
2.15.1 Problem
You want to convert a
string (e.g., "0b10110",
"0x55", or "0755") containing a
binary, octal, or hexadecimal number to the correct number.
Perl understands numbers specified in binary (base2), octal
(base8), and hexadecimal (base16) notation only when they occur as
literals in your programs. If they come in as data—such as by
reading from files or environment variables, or when supplied as
commandline arguments—no automatic conversion takes place.
2.15.2 Solution
Use Perl's
hex function if you have a hexadecimal string like
"2e" or "0x2e":
$number = hex($hexadecimal); # hexadecimal only ("2e" becomes 47)
Use the
oct function if you have a hexadecimal string like
"0x2e", an octal string like
"047", or a binary string like
"0b101110":
$number = oct($hexadecimal); # "0x2e" becomes 47
$number = oct($octal); # "057" becomes 47
$number = oct($binary); # "0b101110" becomes 47
2.15.3 Discussion
The oct function converts octal numbers with or
without the leading "0"; for example,
"0350" or "350". Despite its
name, oct does more than convert octal numbers: it
also converts hexadecimal ("0x350") numbers if
they have a leading "0x" and binary
("0b101010") numbers if they have a leading
"0b". The hex function converts
only hexadecimal numbers, with or without a leading
"0x": "0x255",
"3A", "ff", or
"deadbeef". (Letters may be in upper or
lowercase.)
Here's an example that accepts an integer in decimal, binary, octal,
or hex, and prints that integer in all four bases. It uses the
oct function to convert the data from binary,
octal, and hexadecimal if the input begins with a 0. It then uses
printf to convert into all four bases as needed.
print "Gimme an integer in decimal, binary, octal, or hex: ";
$num = <STDIN>;
chomp $num;
exit unless defined $num;
$num = oct($num) if $num =~ /^0/; # catches 077 0b10 0x20
printf "%d %#x %#o %#b\n", ($num) x 4;
The # symbol
between the percent and the three nondecimal bases makes
printf produce output that indicates which base
the integer is in. For example, if you enter the number
255, the output would be:
255 0xff 0377 0b11111111
But without the # sign, you would only get:
255 ff 377 11111111
The following code converts Unix file permissions. They're always
given in octal, so we use oct instead of
hex.
print "Enter file permission in octal: ";
$permissions = <STDIN>;
die "Exiting ...\n" unless defined $permissions;
chomp $permissions;
$permissions = oct($permissions); # permissions always octal
print "The decimal value is $permissions\n";
2.15.4 See Also
The "Scalar Value Constructors" section in
perldata(1) and the "Numeric Literals" section
of Chapter 2 of Programming Perl; the
oct and hex functions in
perlfunc(1) and Chapter 29 of
Programming Perl
