Converting Binary, Octal, and Hexadecimal Numbers (Perl Cookbook, 2nd Edition)

## 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 (base-2), octal (base-8), and hexadecimal (base-16) 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 command-line 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 non-decimal 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

Copyright © 2003 O'Reilly & Associates. All rights reserved.