You probably don’t need to know how to do this unless you are in serious trouble, but I want to know how to do it anyway. I’ve been slowly working my way through Computer Systems: A Programmer’s Perspective, where I re-learned how to do this arithmetic. I thought it was interesting, so I wanted to share the knowledge with you.
Visualizing Hexadecimal Numbers
The decimal system makes intuitive sense for us humans. Since we have ten fingers, let’s make a number system with ten digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Computers, on the other hand, work best with binary numbers, 0 and 1. Some computers used the decimal system, but they didn’t last.
But binary numbers get really long, really fast. For instance, to represent 2,345,876 in binary, it’s:
1000111100101110010100
A seven-digit number now requires twenty-two digits!
In the past, some coding required the use of binary. For instance, the Unix operating system for the PDP-7 computer was originally written entirely in machine language by Ken Thompson, Dennis Ritchie, Doug McIlroy, and Joe Ossanna at Bell Labs. If that doesn’t make you feel like a weak programmer, I don’t know what will.
Of course, an operating system back then was much simpler. But they still did it binary. Binary numbers are long and hard to read, so we fixed them with hexadecimal notation.
Hexadecimal numbers are base-16 numbers. That means there are 16 symbols to work with rather than 2 or 10: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. This allows for a much shorter notation. 2,345,876 becomes 23CB94. Hexadecimal numbers are usually preceded by a 0x or 0X to indicate that the number is in hexadecimal. With that notation in mind, our number becomes 0x23CB94, which is shorter than binary or decimal.
Another useful property of hexadecimal numbers is that each hexadecimal digit neatly represents a group of 4 binary digits, which is half a byte (A.K.A a nibble). This allows for any byte to be easily represented with only two characters, and you can easily convert from binary to hexadecimal and vice versa with a handy chart:
Hex Digit | Decimal Value | Binary Value
-----------------------------------------
0 | 0 | 0000
1 | 1 | 0001
2 | 2 | 0010
3 | 3 | 0011
4 | 4 | 0100
5 | 5 | 0101
6 | 6 | 0110
7 | 7 | 0111
8 | 8 | 1000
9 | 9 | 1001
A | 10 | 1010
B | 11 | 1011
C | 12 | 1100
D | 13 | 1101
E | 14 | 1110
F | 15 | 1111
To convert from binary to hexadecimal, split the binary number into groups of four. If the binary does not evenly split into groups of four, pad the left with 0’s until it does. Then, use the chart to convert each nibble into the corresponding hex code.
Try it yourself with these practice problems. Answers are at the bottom of the article.
Convert 0xF64A1 to binary
Convert 1101111011000111 to hexadecimal
Convert 0xFF54 to binary
Convert 101111100011001 to hexadecimal
How to Add In Hexadecimal
We can add two hexadecimal numbers using long-hand notation the same way we would add decimal numbers. Place the two numbers to be added one underneath the other and add each place to the other, e.g., 1’s place to the 1’s place, 16’s place to 16’s place, and so on.
Let’s do an example by adding 0x503C and 0x8. To set the problem up, it looks like this:
0x503C
+0x0008
-------
Now, we’ll add the 16’s column. 8 and C in hexadecimal produce 4 with a carry of 1. This is not immediately obvious.
If we convert it to decimal, we can see why. C is 12 in decimal, and 8 is 8. 8 + 12 = 20. 20 in hexadecimal is 0x14. Why is it 0x14? 0x10 represents 16 in decimal because the 1 is in the 16’s place. Numbers in the 16’s place represent that number times 16. The same goes for the next place in hexadecimal numbers, but they are multiples of 256 (16 squared) instead of 16.
1
0x503C
+0x0008
-------
4
The rest of the numbers are added as you would expect. No more carries.
1 (carry)
0x503C
+0x0008
-------
5044
Here are some more practice problems:
Add 0x1234 to 0xABCD
Add 0x1111 to 0x2AFE
How to Subtract In Hexadecimal
Subtraction works much the same way as addition.
We’ll run a problem: 0x503C - 0x40. First, we line up the places and get the problem ready:
0x503C
-0x0040
-------
Now we can proceed to subtract each digit in the minuend from the corresponding digit in the subtrahend.1 0 subtracted from C is C.
0x503C
-0x0040
-------
C
4 subtracted from 3 results in a borrow from the 3rd digit. But since the 3rd digit is a 0, we have to borrow from the 4th. This turns the 5 into a 4, the 0 into an F, and the 3 into a 0x13 - the decimal equivalent of 19. 4 subtracted from 19 is 15, the hexadecimal equivalent of F. This results in an F in the 16’s place. The remaining digits are subtracted normally. You can use the same trick of converting from hex to decimal to work out the borrowing that we used for the carries in the addition problem.
4F (borrowed values)
0x503C
-0x0040
-------
4FFC
Here are some practice problems:
0x55BF - 0x44AD
0x55BF - 0x63AD
Answers to the Practice Problems
11110110010010100001
0xDEC7
1111111101010100
0x5F19. You have to add a 0 to the left of this binary number to make it split into groups of 4.
0xBE01. The first two places of this problem both carry. Try using hex-to-decimal conversion to work it out.
0x3C0F. Again, there is a carry in the 16’s place, resulting in an unexpected 0.
0x1112
-0x0DEE. Yikes! In this problem, the subtrahend is bigger than the minuend. To do it by hand, you have to swap their places, subtract normally, and then make the result negative. There are three borrows to perform as well.
The minuend is the number being subtracted from. The subtrahend is the number being subtracted.
After reading this article, I'm not feeling good...