(Updated March 24, 2020)
Table of contents
Overview
Numbers systems are simply the means by which we represent values given a particular radix. The radix represents the base counting system. As a defined standard we generally use the Hindu-Arabic numerals of the base 10 counting system, or simply base 10 (decimal).
Other systems of numbers have existed over the ages. The Mayans used base 20 (vigesimal) and the Babylonians of ancient Mesopotamia used base 60 (sexagesimal). Fortunately, our additional counting systems described here will not be quite as difficult to understand. The focus of this paper is on base 2 (binary), base 8 (octal) and base 16 (hexadecimal). In addition to the discussion of numbers of differing radix, you may be interested the concept of bitwise operators which are useful in determining current state or altering a given bit or set of bits.
Take the number 4096. By itself it appears to be a base 10 number. However, since we will be discussing several different radix values, how do we know the difference between 10, 10, 10 and 10? So maybe that was not very clear. Rather, how do we know the difference between 10 as a base 2 value, 10 as a base 8 value, 10 as a base 10 value and 10 as a base 16 value? The only true means of defining the correct radix of a number when viewing it amidst other numbers of conflicting radix is to denote the base as a subscript. The same set of numbers for base 2, base 8, base 10 and base 16 respectively are:
Clearly each of these numbers represents a different value when converted to base 10. This standard convention will be used throughout the remainder of the radix discussions. With respect to each radix, there are a couple of details we must keep in mind. Take the value 409610 for example. First, remember that each radix defines its working set of digits as the range {0..(radix1)}.
For base 10 this is {0..9}. Second, to use a digit outside the range of digits for the given radix is a violation and the number is meaningless. For example, 3848 does not make any sense as a number. This is due to the fact that, for base 8 the range of valid digits is {0..7}. Therefore, 3848 is an invalid representation given the specified radix.
Decimal
No discussion of changing radix should be remiss in a refresher of how base 10 works. Now, you may feel as though you have a good handle on the mechanism of your well-known Hindu-Arabic number system, but do not skip this section. It is the mechanism and not the value of the numbers themselves that is of importance here.
Let us look at 409610 again. We already understand the concept of digit value, but let us recall the importance of place value, also known as position value. Moving through the number from right to left we recall that we have the ones, tens, hundreds, thousands, ten-thousands and so on. Why is that exactly? Well, we need to recall that each position is a function of radix raised to a given power. This is demonstrated below:
100 = 1 = ones position 101 = 10 = tens position 102 = 100 = hundreds position 103 = 1,000 = thousands position 104 = 10,000 = ten-thousands position 105 = 100,000 = hundred-thousands position 106 = 1,000,000 = millions position
Therefore:
409610 is 4 * 103 = 4000 + 0 * 102 = 0 + 9 * 101 = 90 + 6 * 100 = 6 ----- 409610
Remember that overall value is attributed to the sum of the products of digit and position value. Now that we have that out of the way, let us look at some other radix values.
Binary
The binary system comes from our use of digital computers and signals which can either be present or not present. Another representation is on (1) or off (0). However you choose to view binary digits or bits, we know that not much information can be represented in a single bit. But when we group several bits together, we can represent much larger quantities.
This is in direct relation to the discussions on 16-, 32- and 64-bit computing. It represents the quantity that computers can work with natively. The following shows the number of unique values that can represented with binary:
8-bit = 28 values = 256 values 16-bit = 216 values = 65,536 values 32-bit = 232 values = 4,294,967,296 values 64-bit = 264 values = 18,446,744,073,709,551,616 values
When the value represented is an address in memory, you can quickly see the reason for the push to 64-bit
computing – a 32-bit address cannot exceed the 4GB boundary!
We will work with 8-bit quantities for demonstration purposes, but you will quickly see how to extend the concept to larger binary numbers.
The position values for an 8bit binary number from right to left are as follows:
20 = 1 21 = 2 22 = 4 23 = 8 24 = 16 25 = 32 26 = 64 27 = 128
Take 101100102 for example. This is converted to base 10 using the following method:
1 * 27 = 128 + 0 * 26 = 0 + 1 * 25 = 32 + 1 * 24 = 16 + 0 * 23 = 0 + 0 * 22 = 0 + 1 * 21 = 2 + 0 * 20 = 0 ---- 17810
To go from base 10 to base 2 we simply reverse the process. We will use 21210 for our example. The process is simply subtracting the next largest bit position until we reach zero. Since we can only use 0 or 1 there is no need to consider a larger multiplier for a given place value.
212 - 128 = 84 [ 1 for the 128 position ] 84 - 64 = 20 [ 1 for the 64 position ] Cannot use a 32. [ 0 for the 32 position ] 20 - 16 = 4 [ 1 for the 16 position ] Cannot use an 8. [ 0 for the 8 position ] 4 - 4 = 0 [ 1 for the 4 position ] Cannot use a 2. [ 0 for the 2 position ] Cannot use a 1. [ 0 for the 1 position ] ^ |--- Binary pattern in this column.
The statements of what we cannot use are important since they will represent that position value with a zero. If we take the bits as they have been stacked, we can say the following:
Octal
The octal system still has roots in computing today. Once used for smaller systems to represent certain values, it was also adopted for Unix permissions on filesystem objects. The Unix chmod (q.v.) command still uses a 3 to 4 digit octal number for specifying access privileges for multiple user classes on a single object.
The way this works is simple, although octal numbers by design do not fit neatly into an 8-, 16-, 32- or
64-bit standard machine word. This is because it takes only three bits to represent an octal digit. Consider the following:
0002 = 08 0012 = 18 0102 = 28 0112 = 38 1002 = 48 1012 = 58 1102 = 68 1112 = 78
Using this table it is easy to convert from octal to binary and back again. So:
The interim step shows each octal digit being converted to its representative bit set. The leading zero was dropped from the final number. Going the other way:
Note that we group bits from right to left. The leftmost grouping has only two bits, so a zero was added to assist with using the table.
Now, let us take a look at converting between base 8 and base 10. First we will establish the position values for base 8:
80 = 1 81 = 8 82 = 64 83 = 512 84 = 4096 85 = 32768
Using the value 3728 the conversion is a follows:
3 * 82 = 3 * 64 = 192 + 7 * 81 = 7 * 8 = 56 + 2 * 80 = 2 * 1 = 2 ---- 25010
Thereby showing that:
Going in the other direction we will use 69010. Note that we must consider the possibility that we need a value larger than 1 for a given position to make the conversion work correctly.
690 - 512 = 178 [ 1 for the 512 position ] 178 - 128 = 50 [ 2 for the 64 position ] 50 - 48 = 2 [ 6 for the 8 position ] 2 - 2 = 0 [ 2 for the 1 position ] ^ |--- Octal pattern in this column
So now we can say that:
Note in the above calculation that 128 is 2-64’s and 48 is 6-8’s.
Hexadecimal
The beauty of hexadecimal is it is one bit longer than octal. Remember that when you add a bit on the left, you are effectively multiplying the range of values by 2. So if a 3-bit quantity can hold 8 values, then a 4-bit quantity must be able to hold 16 values.
The use of base 16 is instrumental in not only conveying large quantities effectively, but also to consistently show 16-, 32- and 64-bit quantities as 4, 8 and 16 digit hexadecimal numbers respectively.
The issue of digit value needs to be addressed here as well. Since the predicted range of values of base 16 is {0..15}, we clearly have a problem. We cannot use a two digit value to represent the multiplier of a selected position value in the number. As a result, the use of A through F (or a through f) will be used to represent the values 10 through 15 respectively.
The following is the basic bit patterns for each base 16 digit:
00002 = 016 10002 = 816 00012 = 116 10012 = 916 00102 = 216 10102 = A16 00112 = 316 10112 = B16 01002 = 416 11002 = C16 01012 = 516 11012 = D16 01102 = 616 11102 = E16 01112 = 716 11112 = F16
Now we apply the same rules as we did when converting between base 8 and base 2:
And for the reverse we will group from right to left:
The position values of base 16 numbers are shown here:
160 = 1 161 = 16 162 = 256 163 = 4096 164 = 65536 165 = 262144
Let us begin by converting A2BC16 to base 10:
A * 163 = 40960 + 2 * 162 = 512 + B * 161 = 176 + C * 160 = 12 ----- 4166010
So we can say clearly that:
It is assumed we understand that A is 10, B is 11, C is 12 and so on. And going from base 10
to base 16 we will convert 4890310 and proceed as follows:
48903 - 45056 = 3847 [ B for the 4096 position value] 3847 - 3840 = 7 [ F for the 256 position value] 7 - 0 = 7 [ 0 for the 16 position value ] 7 - 7 = 0 [ 7 for the 1 position value] ^ |--- Hexadecimal pattern in this column
So we can say clearly that:
Note in the above calculation that 45056 is 11-4096’s and 3840 is 15-256’s. Also note that we knew that the answer would be a four digit value since the base 10 value was less than 65536.