Any discussion about computers involves discussing binary numbers, but not everyone has experience with that number system. Before we dive into any new number systems, I thought it would be a good idea to talk about a number system you already know. It is my hope that once you understand the breakdown of the number system you currently use, you’ll understand the new systems without many problems.
What is a decimal? Decimal is a number system that you’re (probably) the most familiar with. The basic digits used are 0-9, so a total of 10 digits, when combined, produce any digit in the decimal system. What does that mean? Let’s play with a number we’re familiar with:
This value is read from left to right, with bigger places on the left. We understand this to mean “five thousand six hundred and seventy-three” however to understand new number systems, first we have to understand the “why” of our current number system. To do that, we will decompose the value into each individual value and see how decimal numbers are constructed. First, let’s talk about number places:
…| ten thousands | thousands | hundreds | tens | ones
Another way to write it:
… | 10000 | 1000 | 100 | 10 | 1
which would be
… | 104 | 103 | 102 | 101 | 100
Math notes: Any number to the power 0 is 1. With that, we start to see a pattern: every position shares a similar base, 10. And each positional move to the left is an increase of 10 times. This is what allows us to construct decimal digits and give them the meaning they have.
Applying the above to our current number, we have 0 ten thousand values, 5 thousand values, 6 hundred values, 7 ten values, and 3 one values. Note that anything bigger than (and thereby to the left of) ten thousand (hundred thousand, for instance) is 0, since our current value isn’t that large. Another, numeric way, of stating the above is:
(10000 * 0) + (1000 * 5) + (100 * 6) + (10 * 7) + (1 * 3)
which would allow us to construct our value of 5673. Go ahead and multiply that out!
We can take the above one step further:
(104 * 0) + (103 * 5) + (102 * 6) + (101 * 7) + (100 * 3)
An important note here is that each position can only have the digit 0-9. If you remember your addition, whenever you add two numbers together and the sum is greater than the max value, you need to carry. For instance:
93 + 17
You start adding from the right and go left. In this case, you add
3 + 7, which is 10 however 10 is too big to fit in the ones position (you can only have 0-9) so we carry the 1 to the left. That gives us
1 + 9 + 1 (the extra 1 from the carry). That gives us 11. Again, 11 is too big to fit in the tens position so we carry the 1.
1 + 0 + 0 (the 0s come from
017) gives us 1. The total being
What are binary numbers? Binary numbers are a base-2 number system, which means the only digits we have are 0 and 1, however, just like decimal, we can use these two digits to construct any binary number:
And, just like decimal, these values are read from left to right. Since we don’t have many years of reading binary under our belts, let’s figure out how to convert binary into decimal.
Much like decimal, binary has a similar breakdown of positions:
…| 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1
… | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20
Which we can use to take a binary number and convert it to decimal. If we wanted to convert 1110101 to decimal, we multiply and add it out like in decimal:
(26 * 1) + (25 * 1) + (24 * 1) + (23 * 0) + (22 * 1) + (21 * 0) + (20 * 1)
which then gives us
64 + 32 + 16 + 0 + 4 + 0 + 1 = 117
We can also take any decimal and convert it to a binary number. Take the above places value:
… | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1
and any decimal, for instance 235. What you do is start at the highest binary places value you can subtract from (without the result going negative) and place a 1 in that spot if you can subtract, then subtract the decimal. Continue with this until you’ve run out of binary places. For 235, we can’t subtract 256 from 235 (we’d have a negative result) but for fun let’s place a 0 there.
We can subtract 128 from 235,
235-128 which leaves us with 107 (and we place a 1 in the right most position):
We can subtract 64 from 107,
107-64 which leaves us with 43 (again placing a 1 in the right most position):
We can subtract 32 from 43,
43-32 which leaves us with 11:
We can’t subtract 16 from 11, so we put a 0 in the right most position, and we still have 11:
We can subtract 8 from 11,
11-8 which leaves us with 3:
We can’t subtract 4 from 3:
We can subtract 2 from 3,
3-2 which leaves us with 1:
Lastly we can subtract 1 from 1,
1-1 which leaves us with 0, and our binary number:
Of course, you can do math with binary numbers just like you can with decimal:
110 + 011
As with decimals, you start on the right hand side, and add each column, keeping in mind that you’re only limited to the numbers 0 and 1, so anything that is larger than 1 is carried.
Starting with the right most column,
0 + 1 is just 1. The middle column is
1 + 1, which is 10 (in binary, not ten!) however 10 is too many digits to fit into one column, so we carry the 1. Finally, on the left most column, we add
1 + 1 + 0 (from the carry), which gives us 10 which again is too many digits so we carry the 1. Now we have a new right most column (because of the carry) so we have
1 + 0 + 0, which is 1. That gives us a total of 1001.
You can confirm we’re right by converting to decimal and checking your work: 6 + 3 = 9
One last note about “places” in binary - it is worth it to note that one binary place (represented by either a 0 or 1) naturally encodes less data in one place value than decimal (0-9). This can easily be proven by looking at the place values above. You get more characters to work with in decimal, which means you can have more data in one place before needing another place.
Hexadecimal numbers are a base-16 numeric system, which means the digits involved are 0-9 as well as A-F (written as 0-F). Because we run out of traditional numbers to use, we use A for 10, B for 11, C for 12, D for 13, E for 14, and F for 15.
I’ll leave applying what you learned above to hexadecimal values as an exercise for the reader.
The reason why we care about hexadecimal when working with binary is that it allows us to more easily and concisely write and read binary numbers. There is a direct relationship between binary and hexadecimal values, and once you lean that, you can go back and forth between the two bases without much effort. But the real goal here is to be able to more easily read and write these values. Taking our most complex example from the top:
This would be a pain to read to someone or to yourself. What you can do instead is represent the value as hex. The translation is simple - starting on the right hand side, break up the binary value into 4 digit blocks, and convert each block to its hex value. If your last block is less than 4 digits, pad the value with 0s on the left hand side. For instance, just breaking the value up into blocks gives you:
1 1010 1010 1011 1010 1010 1010 1010 0101 0110
As you see, the right most block only has one digit, so left pad with 0s up to 4 digits:
0001 1010 1010 1011 1010 1010 1010 1010 0101 0110
Left padding with zeros will not change the value (it’s like saying add 0s to the left side of a decimal: 10 is still 10 even written as 0000010). Then, using this handy conversion table, convert each block of 4 digits to its hex value:
which gives us the hex value of 1AABAAAA56. I hope you can see that reading (and talking about) 1AABAAAA56 is much easier than 1101010101011101010101010101001010110.
Other number systems
There are a few number systems I think are worth talking about as well which I will briefly cover.
Base 8 (Octal)
Much like the above, you have 8 digits, 0-7. I think this is cool is because there are tribes of people who don’t use their fingers to count, but use the space between their fingers. Source
Base 64 gives us a way to encode a binary into a system which allows 64 values per position.