I'm studying hexadecimal to decimal conversions for packet header analysis (IP, TCP, UDP, etc).
Trying to come up with a cheat sheet to make the whole thing easier to remember.
First of all each numbering system has a single character representing each possible single digit value. After these values are used up you start tacking these single digits together to come up with bigger values.
For example the single digit values for each of the following numbering systems are:
Binary = base 2 = 0, 1
Decimal = base 10 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Hexadecimal = base 16 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
In the list of characters above for hexadecimal the letters are just a way to use a single character for a two digit decimal number. So our 16 base numbers are 0-15 and we use letters for 10-15 (which are 2 digit numbers) as follows:
A = 10
B = 11
C = 12
D = 13
E = 14
F = 15
So why the heck are we making this all complicated and using these crazy numbering schemes instead of the decimal numbering system we know and love? Computers need a way to store and represent numbers. They don't have fingers. They have circuits. (I'm probably way over-simplifying this - intentionally) These [Boolean] circuits can either be on or off. I like to think of it as a row of light switches. Flip some of them on, some of them off. On is represented as 1 and off is represented as 0.
So let's say you had a row of 4 light switches and starting from right to left, first is off, second is on, third is on, fourth is off. That would look like:
0 1 1 0
The light switches on or off allow you to represent a binary number. So what's that binary number in decimal? Binary is base 2. For each position that has a 1, we take the value of the position (starting with position 0) to the power of 2 and add up the results to get the decimal number. So we have in this case positions: 3, 2, 1, 0. Position 1 and position 2 have a value, position 0 and position 3 don't so:
(0) + (2
2) + (2
1) + (0) = 0 + 4 + 2 + 0 = 6
So 0 1 1 0 in binary (or circuits in a computer turned on and off) = 6 in decimal
So what's hexadecimal for anyway? It takes less space to represent a hexadecimal number where a single hexadecimal digit can represent four binary digits. In other words instead of representing 15 as 1 1 1 1 we can just use F. Hexadecimal is used instead of decimal because 10 is not a value that comes from 2
x, so it's not easy to translate a series of 1's and 0's to base 10.
In computer terminology each single digit of storage (circuit on or off, i.e. 1 or 0) is a called a "bit". 8 bits = a "byte". 4 bits = half a byte or a"nibble". (har har)
One hexadecimal character is 4 bits (with a 1 or a 0 in each spot). If you think about it, it makes sense. Turn all four bits on (1) and calculate the decimal number:
1 1 1 1
or: (2
3 = 8) + (2
2 = 4) + (2
1 = 2) + (2
0 = 1) = 15 (counting from 0 to 15 = 16 digits).
We can turn that single four digit binary number into a 1 digit hexadecimal number and store 1 digit instead of 4
Ok now we want to take a hexadecimal digit and convert it to decimal. So let's take 6, for example.
We'll have four bits to represent 6.
_ _ _ _
OK so for each of those spots we have to either put in a 1 or a 0 as required to represent a 6. If each of those slots represents a binary value and if each spot were filled with a 1 we'd have these decimal values for each corresponding position (again 2
0, 2
1, etc.):
8 4 2 1
Ok so how do we come up with 6? 4 + 2. So the slots for 4 and 2 are set to 1 and the slot for 1 and 8 are set to 0. That gives us binary 6:
0 1 1 0
Let's try D. D in hexadecimal = 13 in decimal as shown above. We will need the slots to have 1 for positions 4, 3 and 1 (8 + 4 + 1) so binary digit D is represented as:
1 1 0 1
Now we can look at this another way to come up with our cheat sheet. We know the decimal value of each hexadecimal digit above. We can map out the binary to hex translation in a table like this:
Hex | | Binary |
0 | | 0 0 0 0 |
1 | | 0 0 0 1 |
2 | | 0 0 1 0 |
3 | | 0 0 1 1 |
4 | | 0 1 0 0 |
5 | | 0 1 0 1 |
6 | | 0 1 1 0 |
7 | | 0 1 1 1 |
8 | | 1 0 0 0 |
9 | | 1 0 0 1 |
A (10) | | 1 0 1 0 |
B (11) | | 1 0 1 1 |
C (12) | | 1 1 0 0 |
D (13) | | 1 1 0 1 |
E (14) | | 1 1 1 0 |
F (15) | | 1 1 1 1 |
It will also be helpful to memorize or table-ize the values of each binary position for our translations from hex to decimal. For each position in a binary number there is a corresponding decimal number which is (2^[position]) or 2
position. We know already that position 0 = 1 (2
0), position 1 = 2 (2
1), position 2 = 4 (2
2) and position 3 = 8 (2
3). Our full table for 16 positions could look like this where each subsequent value doubles the value in the prior position:
Position | Decimal |
0 | 1 |
1 | 2 |
2 | 4 |
3 | 8 |
4 | 16 |
5 | 32 |
6 | 64 |
7 | 128 |
8 | 256 |
9 | 512 |
10 | 1024 |
11 | 2048 |
12 | 4096 |
13 | 8192 |
14 | 16384 |
15 | 32768 |
Ok now let's say we have some crazy looking Hexadecimal number that looks like this:
AE06
First of all we know there are four bits for each hex digit:
_ _ _ _ | _ _ _ _ | _ _ _ _ | _ _ _ _
Now as above we know that for each four slots we'll have 8 6 4 2 as the decimal representation of 1 1 1 1. So let's translate that crazy hex number into binary one character at a time.
A = 10 as shown above and in our chart we see that is 1 0 1 0.
E = 14 and that is 1 1 1 0
0 = 0 and that is 0 0 0 0
6 = 6 and that is 0 1 1 0
Put that all together and what does it spell?! Ok I'll get out of cheerleader mode now.
1 0 1 0 1 1 1 0 0 0 0 0 0 1 1 0
What do we do with that?? Well we know that it's base 2 so for each digit we calculate 2
position and add up the result. So we have a 1 in positions (starting with position 0 on the right): 1, 2, 9, 10, 11, 13, 15.
We can grab the decimal value for each of those binary digit positions from the above binary position to decimal table and add them up:
2 + 4 + 512 + 1024 + 2048 + 8192 + 32768 = 44550
We can check that calculation on the handy dandy Windows calculator. Open it up and choose "programmer" from the view menu. Click on the "hex" radio button. Enter AE06. Then click on the decimal radio button. Yay it worked! I'm typing this all up from scratch and I guess I got it figured out.
Hopefully having the translation cheat sheets above will help in a pinch, or can go the route of memorizing all of the above - kind of like my parents used to grill into me and their grade school students to learn their math facts :)
Related - Translating IP headers (and UDP, TCP, etc. not mentioned in the post below) from Hex to meaningful values humans can understand - I'm assuming here most people don't speak hex.
http://websitenotebook.blogspot.com/2014/03/ip-internet-protocol_1.html