Binary numbers are a great way for computers to represent numbers. They're not as great for humans though—they're so very long, and it takes a while to count up all those $1$s and $0$s. When computer scientists deal with numbers, they often use either the decimal system or the hexadecimal system. Yes, another number system!
Fortunately, number systems are more alike than they are different, and now that you've mastered decimal and binary, hexadecimal will hopefully make sense.
In the decimal system, each digit represents a power of $10$—the ones' place, the tens' place, etc. We call $10$ the base of the decimal system.
[[☃ graded-group 1]]
In the hexadecimal system, each digit represents a power of $16$.
Here's how to count to 10 in hexadecimal: $1$, $2$, $3$, $4$, $5$, $6$, $7$, $8$, $9$, $\text{A}$.
That looks very familiar until the final "number" $\text{A}$. You see, in the hexadecimal system, each digit needs to represent the values $0$-$15$, but the decimal numbers $10$-$15$ don't fit into a single digit. To work around that, the hexadecimal system uses the letters $\text{A}$-$\text{F}$ to represent the numbers $10$-$15$.
Here, let's count from 10 to 15: $\text{A}$, $\text{B}$, $\text{C}$, $\text{D}$, $\text{E}$, $\text{F}$. Strange but true!
There's actually been many different proposals over the years for how to represent the values 10-15, but $\text{A}$-$\text{F}$ is the solution that won out.
Let's count higher now. Here's the decimal number $24$, represented in hexadecimal as $18$:
$1$ | $8$
- | - | - | -
$16$ | $1$
$16^1$ | $16^0$
This number requires two digits, where the right digit represent the ones' place ($16^0$) and the left digit represents the sixteens' place ($16^1$). The same way that we added decimal and binary numbers, we can add up $(1 \times 16) + (8 \times 1)$ and see that hexadecimal $18$ equals the decimal value $24$.
Let's try a number with a letter in it. Here's the decimal number $27$, represented in hexadecimal as $1\text{B}$:
$1$ | $\text{B}$
- | - | - | -
$16$ | $1$
$16^1$ | $16^0$
To understand this one, we need to first remember that $\text{B}$ represents the value $11$. I do that by counting the letters on my fingers, but you can count however you'd like, as long as you remember to start with $\text{A}$ representing $10$.
Then we can add it up like before and see that $(1 \times 16) + (11 \times 1)$ does equal the decimal value $27$.
[[☃ graded-group 1]]
Why base 16?
At this point, you might be wondering what it is that computer scientists like so much about the hexadecimal system. Why use a system where we have to use letters to represent numbers? A little detour into history will show us why...
Early computers used 4-bit architectures, which meant that they always processed bits in groups of 4. That's why we still write bits in groups of 4, like when we write $0111$ to represent decimal $7$ even though we could just write $111$.
How many values can 4 bits represent? The lowest value is $0$ (all $0$s, $0000$) and the highest value is $15$ (all $1$s, $1111$), so 4 bits can represent 16 unique values. Aha, there's that number 16!
Each group of 4 bits in binary is a single digit in the hexadecimal system. That makes it really easy to convert binary numbers to hexadecimal numbers, and it makes it a natural fit for computers to use as well.
Converting binary to hexadecimal
Let's prove how well binary and hexadecimal get along by converting from binary to hexadecimal.
We'll start with a short binary number:
$0010\text{}$
That's 4 bits long, which means it maps to a single hexadecimal digit. There's a $0$ in every place except the twos' place, so it equals the decimal number $2$. The decimal and hexadecimal systems both represent the numbers $0$-$9$ the same way, so $0010$ is simply $2$ in hexadecimal.
Let's try a longer binary number:
$1001,1010 ,0110,1100\text{}$
One approach would be to figure out what decimal number is represented by that long string of $1$s and $0$s, and then convert that to hexadecimal. That approach would work, but gosh, it seems like a lot of work for this long of a number.
The easier approach is to convert each group of 4 bits, one at a time.
Starting with the left-most group of $1001$, that equals $(1 \times 8) + (1 \times 1)$, the decimal number $9$. That number is less than $10$, so $1001$ is simply $9$ in hexadecimal.
The next group is $1010$, or $(1 \times 8) + (1 \times 2)$, the decimal value $10$. That number requires a letter representation in hexadecimal, $\text{A}$.
The next group is $0110$, or $(1 \times 4) + (1 \times 2)$, the decimal value $6$. That number is the same in hexadecimal, $6$.
The final group is $1100$, or $(1 \times 8) + (1 \times 4)$, the decimal value $12$. That number requires a letter representation in hexadecimal, $\text{C}$.
Our final hexadecimal result is $9\text{A}6\text{C}$. We did that conversion without ever understanding what decimal number is represented. I'll reveal now that both $1001,1010 ,0110,1100$ and $9\text{A}6\text{C}$ equal the decimal number $39,532$. That's an awfully big number, I'm glad we converted it one digit at a time.
[[☃ graded-group 1]]
Patterns in hexadecimal numbers
Let's build some intuition around the hexadecimal system.
First: for a given number of digits, what does the biggest number look like for those digits? In the decimal system, that's all $9$s, like $9,999$. In the binary system, that's all $1$s, like $1111$.
In the hexadecimal system, that's when every digit has an $\text{F}$ in it, $\text{FFFF}$. When we see a number like that, we know that it represents the highest possible value for that number of digits. To represent any higher number, we'd need more digits.
Okay, now how much does a big number like that represent? We can use the same rule that we used for binary: the largest number that can be represented by a number of digits $n$ is the same as $16^n - 1$. Now that we're dealing with base 16 instead of base 2, we might need to bring out a calculator to figure that out though.
Here's a table of the first four largest values:
| Digits | Highest hexadecimal number | Decimal equivalent |
|---|---|---|
| 1 | $\text{F}$ | $15,(16^1 - 1)$ |
| 2 | $\text{FF}$ | $255,(16^2 - 1)$ |
| 3 | $\text{FFF}$ | $4095,(16^3 - 1)$ |
| 4 | $\text{FFFF}$ | $65535,(16^4 - 1)$ |
[[☃ graded-group 1]]
Uses for hexadecimal
In this unit on how computers work, we're mostly going to be dealing with binary numbers. It's important to understand the hexadecimal system as well though, because they'll pop up throughout later units and just generally, in the life of a programmer.
As one example from my life, web developers use hexadecimal numbers to represent colors. We describe colors as a combination of three components: red, green, and blue. Each of those components can vary from $0$ to $255$. A color like blue can be written as rgb(0, 0, 255) or the more concise hexadecimal version, #0000FF. Using that notation, we can describe $16^6$ unique colors—more than 16 million colors!
Now that you know about hexadecimal numbers, keep your eyes out for them. You'll often see them written with an 0x in front, like 0x4F, or you might just recognize their distinctive mix of 0-9 with A-F. If you spot any interesting uses for them in the wild, share your discovery below in the Tips & Thanks.