Last updated:

In my article about base-2 (binary) numbers I talked about the difference between the decimal (base-10) numbers we use in our everyday life and base-2 numbers. This article looks at hexadecimal (base-16) numbers. Understanding the base-16 system is crucial for understanding IPv6 addresses.

As a quick recap, the decimal system uses ten digits: 0 to 9. Of course, you can count beyond 9. To do so you simply use more than one digit. So, to get past 9 you change the value to 0 and add a 1 to the left. That gives you the number 10.

The base-2 system has just two values: 0 and 1. To represent a number greater than 1 you again use more than one digit. To get to the number 2 you change the number to 0 and stick a 1 in front of it. So, in base-2 the number 2 is written as 10.

Base-16 uses 16 values: the numbers 0 to 9 and the letters A to F. Up to the number 9 the decimal and hexadecimal systems are identical: a base-10 number 9 is also a 9 in base-16. We don’t have a single number for ten, which is why base-16 uses the letters A to F. The letter A is 10, B is 11 etc.

The below table shows how base-10, 2 and 16 numbers are increased. Can you guess what the decimal number 16 is in base-2 and base-16?

Base-10 | Base-2 | Base-16 ---------+--------+-------- 0 | 0 | 0 1 | 1 | 1 2 | 10 | 2 3 | 11 | 3 4 | 100 | 4 5 | 101 | 5 6 | 110 | 6 7 | 111 | 7 8 | 1000 | 8 9 | 1001 | 9 10 | 1010 | A 11 | 1011 | B 12 | 1100 | C 13 | 1101 | D 14 | 1110 | E 15 | 1111 | F

For both you need to change the number to 0 and add a 1 to the left. The base-2 representation of the decimal 15 is 1111, so 16 becomes 10000. Similarly, the letter F is the largest value in base-16. So the next value becomes 10.

The above table is handy, but it doesn’t help you convert large base-16 numbers to base-10. Of course, there is a formula to convert base-16 to base-10. For each hexadecimal character you need to calculate the decimal value and then add up the total. To calculate the individual decimal values you work from right to left. The right-most hex value is multiplied by 16^{0}, the next by 16^{1} and so forth.

That is a bit abstract, so let’s look at some examples. We can start by amending the above table. All the base-16 values have just one character. So, the formula is simply the base-16 number times 16^{0}. As 16 * 0 equals 0 the values don’t change:

Base-10 | Base-16 to Base-10 ---------+------------------------ 0 | 0 x 16^{0}= 0 1 | 1 x 16^{0}= 1 2 | 2 x 16^{0}= 2 3 | 3 x 16^{0}= 3 4 | 4 x 16^{0}= 4

It is worth noting that the “zero power” always returns 1, and not 0 as you might expect (I cover why in my article about base-2 numbers). So, in effect we just multiply the right-most value by 1.

Next, let’s look at the base-16 number 10. We now got two values: 1 and 0. To convert the hex number we start with the right-most value and multiply it by 16^{0}. That gives us zero, as 0 * 1 equals nothing. Next, we take the 1 and multiply it by 16^{1}. That returns 16, and so the hexadecimal number 10 translates to the decimal number 16 (16 + 0 = 16).

You can write the calculation as follows:

(1x16^{1}) + (0x16^{0}) = 16

Or, you might find this more readable:

1 x 16^{1}16 0 x 16^{0}0 ---- Base-10 16

If that made sense then we can try something more challenging: converting *ACDC* to decimal. To do so you perform the same magic. You start with the right-most value (a *D*, which is the decimal number 12) and work your way to the left:

10 x 16^{3}= 10 x 4096 = 40960 12 x 16^{2}= 12 x 256 = 3072 13 x 16^{1}= 13 x 16 = 208 12 x 16^{0}= 12 x 1 = 12 ----- Base-10 44252

Converting a base-10 number to a hexadecimal works much like converting a base-10 number to a binary number. You divide the number by the exponent (16) and keep dividing the result until the quotient is 0. At each step you multiply the remainder by 16 to get the hex value.

As always, it is easiest to explain this with some examples. Let’s recycle the decimal number *44252* and check if it translates to *ACDC*:

Quotient | 16 * Remainder | Hex ------------------------------+------------------+----- 44252 / 16 = 2765.75 (2765) | 16 * .75 = 12 | C 2765 / 16 = 172.8125 ( 172) | 16 * .8125 = 13 | D 172 / 16 = 10.75 ( 10) | 16 * .75 = 12 | C 10 / 16 = 0.625 ( 0) | 16 * .625 = 10 | A

The final step is to string together the hex values, starting with the last value. So, that gives us *ACDC*.

To give one more example, the same recipe works for the decimal number *16*:

Quotient | 16 * Remainder | Hex ------------------------------+------------------+----- 16 / 16 = 1.0 ( 1) | 16 * 0 = 0 | 0 1 / 16 = 0.0625 ( 0) | 16 * 0.0625 = 1 | 1

Of course you can also convert from binary to hexadecimal and vice versa. To convert base-2 to base-10 you split the binary value into blocks of four digits (known as *nibbles*) and then look up the hex value for each block. To look up the hex values you can refer to a slightly amended base-2, 10 and 16 table:

Base-10 | Base-2 | Base-16 ---------+--------+-------- 0 | 0000 | 0 1 | 0001 | 1 2 | 0010 | 2 3 | 0011 | 3 4 | 0100 | 4 5 | 0101 | 5 6 | 0110 | 6 7 | 0111 | 7 8 | 1000 | 8 9 | 1001 | 9 10 | 1010 | A 11 | 1011 | B 12 | 1100 | C 13 | 1101 | D 14 | 1110 | E 15 | 1111 | F

The only difference with the table I showed earlier is that all the base-2 numbers now have four digits (i.e. they use leading zeros if applicable). This makes it easier to look up the hex values.

For instance, the decimal number *16* is *10000* in binary. The number has five digits, so you add three leading zeros to get two groups of four digits:

0001 0000

You can next use the above table to find the hex values for the two blocks:

0001 = 1 0000 = 0

So, we got a 1 and 0, which gives us the hex value *10*.

Let’s try same again using a larger number:

1010 1100 1101 1100 A C D C

That’s right, we are back with *ACDC*!

Converting a hexadecimal number to binary is the reverse process. You take each hex digit and look up the binary value. Let’s convert *ACDC* and *10* one more time:

Base-16 | A C D C Base-2 | 1010 1100 1101 1100 Base-16 | 1 0 Base-2 | 0001 0000