An often asked question in the Java forum is "How can I convert a binary string to a decimal number?". While most forum posters will be quick to point out that this is easy to do using
Integer.parseInt using radix 2, this is usually not the answer people are looking for. Similarly, one can use
Integer.parseInt with radix 8 and 16 to achieve similar results for octal and hexadecimal, respectively.
However, the goal of this tutorial is not to point out the rather obvious existence of this method, but to teach someone how such a conversion is actually achieved.
Binary to decimalA binary number is a number in base 2. This means that only valid digits are 0 and 1, and a binary number often looks like 00101010, which in decimal is 42. Binary numbers are often grouped in groups of 8, commonly referred to as bytes.
It is important to realize that each digit in a binary number represents a power of 2, with the rightmost bit ("binary digit") representing 2^0, and each position you move to the left increases the power by 1, for the 1st eight bits this means:
Bit 0 (rightmost) = 2^0 = 1
Bit 1 = 2^1 = 2
Bit 2 = 2^2 = 4
Bit 3 = 2^3 = 8
Bit 4 = 2^4 = 16
Bit 5 = 2^5 = 32
Bit 6 = 2^6 = 64
Bit 7 = 2^7 = 128
Now - what a binary number is is simply a multiplication - each bit tells you whether or not the given power of 2 should be included in the decimal number.
0101 then simply means:
0 * Bit 3 + 1 * Bit 2 + 0 * Bit 1 + 1 * Bit 0
So how do we turn this into an algorithm? Basically what we do is loop through our String from right to left and check each multiplication as we go:
java
public static long binaryToDecimal(String binary) throws NumberFormatException {
// Initialize result to 0
long res = 0;
// Do not continue on an empty string
if (binary.isEmpty()) {
throw new NumberFormatException("Empty string is not a binary number");
}
// Consider each digit in the string
for (int i = 0; i < binary.length(); i++) {
// Get the nth char from the right (first = 0)
char n = binary.charAt(binary.length() - (i+1));
// Check if it's a valid bit
if ((n != '0') && (n != '1')) {
// And if not, die horribly
throw new NumberFormatException("Not a binary number");
} else if (n == '1') {
// Only add the value if it's a 1
res += Math.round(Math.pow(2.0, i));
}
}
return res;
}
Octal to decimalAn octal number is a base 8 number, and has 0, 1, 2, 3, 4, 5, 6, 7 as valid values for it's digits. As with binary numbers, each digit in an octal number represents a power of 2. The first digit is 2^0, the second one 2^3, and the nTH one 2^(3*n). The value of each digit represents a factor with which to multiply this power of 2:
152 = 1 * 2^6 + 5 * 2^3 + 3 * 2^0 = 1*64 + 5*8 + 2*1 = 64 + 40 + 2 = 106
Turning this into an algorithm is similar to doing binary to decimal:
java
public static long octalToDecimal(String octal) throws NumberFormatException {
// Initialize result to 0
long res = 0;
// Do not continue on an empty string
if (octal.isEmpty()) {
throw new NumberFormatException("Empty string is not an octal number");
}
// Consider each digit in the string
for (int i = 0; i < octal.length(); i++) {
// Get the nth char from the right (first = 0)
char n = octal.charAt(octal.length() - (i+1));
int f = (int) n - 48;
// Check if it's a valid bit
if (f < 0 || f > 7) {
// And if not, die horribly
throw new NumberFormatException("Not an octal number");
} else {
// Only add the value if it's a 1
res += f*Math.round(Math.pow(2.0, (3*i)));
}
}
return res;
}
Hexadecimal to decimalHexadecimal numbers are numbers in base 16, with digits having the following possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Each digit in a hexadecimal number represents a power of 2. The first digit is 2^0, the second one 2^4, and the nTH one 2^(4*n) - with the first one being the 0th digit. The value of each digit indicates the factor with which it should be multiplied (A-F count as 10-15).
The algorithm for converting hexadecimal to decimal is analogous to the octal to decimal conversion:
java
public static long hexadecimalToDecimal(String hex) throws NumberFormatException {
// Initialize result to 0
long res = 0;
// Do not continue on an empty string
if (hex.isEmpty()) {
throw new NumberFormatException("Empty string is not a hexadecimal number");
}
// Consider each digit in the string
for (int i = 0; i < hex.length(); i++) {
// Get the nth char from the right (first = 0)
char n = hex.charAt(hex.length() - (i+1));
int f = (int) n - 48;
// Try to fix A-F values
if (f > 9) {
// A-F
f = f - 7;
if (f > 15) {
// a-f
f = f - 32;
}
}
// Check if it's a valid bit
if (f < 0 || f > 15) {
// And if not, die horribly
throw new NumberFormatException("Not a hexadecimal number");
} else {
// Only add the value if it's a 1
res += f*Math.round(Math.pow(2.0, (4*i)));
}
}
return res;
}
Alternative methodsIn addition to doing octal and hexadecimal to decimal conversions directly, it is also possible to convert these numbers to binary first and then do binaryToDecimal. This can be done by replacing each digit by several binary ones:
For octal:
0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101
6 = 110
7 = 111
For hexadecimal:
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