Many electronic and microcontroller projects require the use of a particular base numbering system, such as BCD on thumbwheel switches, hexadecimal (base-16) on hex encoders, and binary in shift registers and dip switches. Often it is necessary to convert between bases, for example, when using a decade counter and converting a BCD value of a switch into a base-10 (that is, decimal) value that can be easily displayed. In particular, all math is done in binary in digital systems, as well as at the analog/digital interface (like when you sample a waveform or measure a voltage) using only two digits: 1 and 0.
This is a brief instructable on what numbers represent and how to convert between the bases in which they are represented. This was included in one of my other guides when I realized that it should be separated out and put into its own instructable. After reading this guide you should be able to look at a binary number like "11101011" and tell that it represents the number 235 or convert the hex value "0xC0E4" to its binary equivalent of "1100000011100100" and decimal representation of 19980 without the use of a calculator (unless you suck apples at addition,subtraction,or division, in which case I feel your pain and wholly suggest keeping your favorite calculator handy).
However, no heavy math is needed and you won't need to do anything outside of basic math so don't sweat it if you're mathematically challenged. This is part of the fun side of math.
Step 1: Understanding Number Representations
As just mentioned and you probably already knew, a number's base dictates how many numbers are used in the counting system. The most common bases are discussed next, but before that a brief detour on what --conceptually--a number means. Let's take the base-10 number, 28810.
Note that I follow convention when a common base is not implied and explicitly state the base as a subscript to the number.
Decimal (base-10, or denary)
What does 28810 mean, exactly? This value explicates that this number encompasses two 100's, eight 10's, and 8 units. This can be succinctly shown as:
28810 = (2 * 100) + (8 * 10) + (8 * 1)
28810 = (2 * 102) + (8 * 101) + (8 * 100)
= 200 + 80 + 8
htun = (h * n2) + (t * n1) + (u * n0) where h=hundreds,t=tens,u=units
As read across left to right, each number increases the total value by that number * base to the power of its place. This notation will become useful when I show you how to convert any base into base-10/decimal in the next step. There's not much to say about denary until a few more steps.
Step 2: Base Basics (Con't): Binary
As the name implies, a binary numbering system consists of two numbers: 1 and 0. Accordingly, this is referred to as base-2 and numbers look like 100100102. In such a system, the representation of values are accomplished through a "power of two" system. Each place in a binary number, often referred to as a bit, has a particular value that can easily be determined. Binary numbers are usually written as a multiple of eight, or a byte. Sometimes, only four bits of the byte, either the upper or lower half are used and these four bits are collectively called a nibble. Nibbles become important when converting between bases as we will see later.
Without digressing, I will be using big endian notation where integers are stored in memory starting with the most significant bit (MSB) and ending with the least significant bit (LSB). The value of any given bit location is determined by taking two (the number of digits in our binary system) to the power of the bit's place using a zero-based index: 2bit. For instance, the LSB of the nibble is 20 or 1. The fourth bit, that is, the third place (remember we start at zero) value is 23 or 8. Let's just look at some examples to make it clearer. Here's how a nibble is represented in binary.
Zero-based index 3 2 1 0 Bit place 4th 3rd 2nd 1st Bit value 8 4 2 1 Example values: Decimal 12 1 1 0 0 Decimal 5 0 1 0 1
If the bit place's value is to be added (or counted) that bit will be a 1, else it will be a 0. Knowing this, the decimal value "1" is written "0001" because the 1st bit is set and that value is one. The decimal value "10" is written in binary as "1010" and if you add the bit place's value where there is a 1 then you will see it adds to 10. In this way, a nibble can represent the numbers 0 through 15. Larger numbers require the use of the high-order nibble.
Bit place 8th 7th 6th 5th 4th 3rd 2nd 1st Bit value 128 64 32 16 8 4 2 1 Example value: Decimal 88 0 1 0 1 1 0 0 0 Decimal 253 1 1 1 1 1 1 0 1
Add the bit values for each bit's place that has a 1 to satisfy yourself that the decimal values are accurately represented by the binary value to its right.
I will cover binary addition, subtraction, multiplication, division, floating points, and negative numbers via 2's complement and 1's complement in a later instructable I've already started working on called How to Calculate like a Microcontroller, but here's a preview as an enticement (yeah, like binary math can be an enticement, right?) to view and rate my other instructables. :)
Preview of How to Calculate Like a Microcontroller.
Binary Arithmetic: Adding and Subtracting
Binary arithmetic is very simple and straight-forward. You should familiarize yourself with the binary representation of numbers zero through three, if you don't already have these committed to heart. They are 00, 01, 10, and 11. The primary thing to remember is to carry over ones and that's the hardest thing you'll have to do, so breathe easy.
I'm going to add 15810 and 5110 in binary, which if you have already added them should yield 20910. Follow along and double-check my calculations.
1001 1110 + 0011 0011 -------------Now, add down from the LSB (far right) moving to the left. The first is 0 + 1 which is 1. The next is 1 + 1 which is 2, but in binary is 10. This is two digits so we have to carry that one over to the next column.
1001 1110 + 0011 0011 ------------- 01 ------------- 1
In that column, it's 1 + 0 + 1 which is again two, or 10. Carry that one. Continue.
1001 1110 + 0011 0011 ------------- 0001 ------------- 1111Now we have 1 + 1 + 1 which is three, or, yes, you got it: 11. So instead of putting a zero and carrying a 1, put a 1 and carry a one. Continue to the end.
1001 1110 + 0011 0011 ------------- 1101 0001 ------------- 111111The 110100012 is 20910, so we did our calculations correctly.
Binary Arithmetic: Multiplication and Division
In the base-2 system, division and multiplication by a power of two is also easily accomplished by right and left shifting, respectively. Shifting is exactly as it sounds: when you left shift by n, you take all the 1's and 0's and move them n places to the left filling in the shifted places with a 0. When you logically right shift by n places, you move all the binary values n places to the right, filling the moved slots with 0's (there is also an arithmetic right shift, but I don't cover it here). In the example below, I shift the number 4 to the left by one bit. The bit #1 is the 2nd from the right in our zero-based index system, and we can also write it 21 or 2. This should cause a multiplication of 4 * 21 or 8.
Left shift: 4 << 1 Bit value: 8 4 2 1 Binary: 4 = 0 1 0 0 Shifted to the left one bit: 1 0 0 0 = 8 denary
You can see how shifting to the left changes the number from four to eight, effectively multiplying the value by two. We could also shift left by two bits or any number of bits from 1 to n - 1, where n is the number of bits in our binary number. Accordingly, shifting a binary number to the right effectively divides the number by a power of two. Think about that if you're not clear then take a look below. Here we shift 32 two bits to the right, effectively dividing 32 by 22 , yielding 8.
Right shift: 32 >> 2 Bit value: 128 64 32 16 8 4 2 1 Binary 32 = 0 0 1 0 0 0 0 0 Shifted to the right two bits: 0 0 0 0 1 0 0 0
That's far from all of the foundational binary operations, but it's an adequate coverage for our lil' 'ol instructable here.
Step 3: Hex isn't a Curse
In this base -- probably the most popular base for programmers -- the numbering system has digits that count up to 16. That is, there is no repeat of numerals from zero to sixteen. Since we only have number representations from zero to nine, the letters "A" through "F" are used. Therefore, the hexadecimal system ranges from zero to F.
Let's count from zero to 32 in hexadecimal.
0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
Easy enough. Hexadecimal numbers are represented usually one of three ways, and predominantly the first two I will show you on systems that cannot support subscripting (that is, good 'ol ASCII).
- Use "0x" before the number, as in 0x1234 or 0xFF
- Use "h" after the number, as in 1234h or FFh
- Use our standard mathematical notation of subscripts: 123416 and FF16
An 8-bit number is represented by two hex numbers and the convention is to zero-fill on 8-bit boundaries. For instance, 0xFF is 25510 while 0xFFFF is 6553510. If the number were to be 409510, which would be 0xFFF, it is nicer to add that zero in front (0x0FFF), although this is by no means always done.
The reason hex is so "wildly" popular with programmers is that it is a more compact and easier to read representation of binary numbers when you are working at the bit level. Often in operations, such as setting values in shift registers, flipping on bits in an LED matrix, etc it is more convenient to write the value as a hex number than full-on binary. This is why I chose hexadecimal as one of the three bases I wanted to cover in base conversion.
That pretty much covers numeric representation of our three bases, so let's actually get into the body of our instructable and rock out some base conversions.
Step 4: Convert any base into denery/decimal (base-10)
Remember back a few steps ago, I showed you the basic formula:
htun = (h * n2) + (t * n1) + (u * n0)Now we're going to put it to good use. Let's convert a hexadecimal value to a denery/base-10/decimal value. Ok pick a value. 0x19F2 ? Ok, sounds good. First, change the hex numbers into dec numbers. These are the individual digits in the number 19F216. Here's a cheat sheet if you've forgotten.
dec 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 hex 0 1 2 3 4 5 6 7 8 9 A B C D E FSo, 1 = 1, 9 = 9, F = 15, 2 = 2.
Using the formula from above, write:
0x19F2 = (1 * 163) + (9 * 162) + (15 * 161) + (2 * 160)this yeilds: = 4096 + 2304 + 240 + 2 = 664210
So, 0x19F2 = 6642 in decimal. Remember, in the original formula, n is the base, so if the base is 16, as in hex, you multiple the digit's place by the base raised to the power of it's zero-indexed place. That sounds confusing even as I write it, but if you look back at the formula and the equation with the numbers filled in it should become clear.
Convert an Oct into a Dec
This is a little bit of the same as before except our base is now 8 instead of 16. Try it with the number 7238 also written \0723 in computer programming notation. Go ahead and convert it. I'll outline the steps below again.
7238 = (7 * 82) + (2 * 81) + (3*80)
= 448 + 16 + 3
8^2 8^1 8^0 64 8 1 x 7 2 3 ----- --- --- 448 + 16 + 3 = 467You can do this with any base, including hex and binary.
Binary to Base-10
I suppose before I conclude this section, I should show an example with binary. Here's one. We'll use the number 010101012. This works the same way as before. Let's try the new way I just showed you instead of the original formula. The binary sequence should look mighty familiar to you by now.
27 26 25 24 23 22 21 20
128 64 32 16 8 4 2 1
0 1 0 1 0 1 0 1
----- --- -- --- --- --- -- ---
0 64 +0+ 16 +0 + 4 +0 + 1 = 8510
See how that works? Try it yourself using the original formula if you're unclear. I've found some bases are easier for me to work on using one equation or the other.
Again, this works with any base, so go hog wild and try some insane base like, oh, base 4 or base 17. This conversion direction (any base to decimal) is the easy one. Flip the page and learn how to convert from denery into binary, hex, and octal.
Step 5: Convert a Decimal Number Into Any Base
Convert a denery number into any base-n
To me, this is the hardest part of converting between bases: from decimal to a different base. However, don't let my math conundrums confound you. The process is very simple and without pitfalls, if not a bit circuitous. We'll try one to get a feel for the process because the process is the same for every base, which is a good thing we don't have to remember a bunch of conversion rules. To prove this point subtly, I'll start off converting a denery number into an odd base, base-7.
Convert 15810 into base7
I. The first step is to take the target base to varying powers and attempt to divide it into the source number to get the largest part.
- 73 = 343 which is larger than 158 so we can't divide a larger number into a smaller number. Step down an exponent.
- 72 = 49 which is smaller than 158. 49 goes into 158 three times with a remainder. 3 * 49 = 147.
- Take the number of times 49 goes into 147 and use it as the first digit of the new base: 3xx7
II. Subtract the product of the multiplication from the dividend of the division. This sounds overly complicated. Put another way, 158 - 147 = 11. We're subtracting (the number of times 72 goes into 158 * 72) from the original base-10 number, or our starting number.
- 158 - 147 = 11
- Since there is one seven in 11, place that in the tens place of the new number: 31x7
- Proceed to Step I.
I'll complete the step here.
- How many 71's are in 11? One and a remainder. 1 * 7 = 7.
- 11 - 7 = 4
- There are no seven's in four: 4 x 1 = 4
- Place the four in the digits section of the base-7 number: 3147
That is our base-7 number: 15810 = 3147
Convert denery into binary
What is 15810 in base-2? We can figure that out now that we have our rules in place. I'll go through it short form, but not an entirely terse fashion. You will need, however, to recall binary value placement. I'll add up the digits into the binary value at the end.
- 28 is 256 and is too big. 27 is 128. 128 goes into 158 one time.
- 158 - 128 = 30
- 24 = 16. 30 - 16 = 14.
- 23 = 8. 14 - 8 = 6.
- 22 = 4. 6 - 4 = 2.
- 21 = 2. 2 - 2 = 0
Notice I didn't move any numbers into the target base locations this time. In binary, we'll either have it going into a number one or zero times. Look back at the calculations as I add the numbers.
128 + 16 + 8 + 4 + 2
128 64 32 16 8 4 2 1 1 0 0 1 1 1 1 0
So the decimal number 15810 is 100111102.
Convert decimal into hexadecimal
Ready to try your hand at converting decimal to hexadecimal? Good, I thought so.
What is 15810 in base-16? First, let's use some intuition. How many digits should the hexadecimal number be? Two, right? The number 158 is less than FF, which is 255.
For converting from decimal to hexadecimal there is a different way that I learned and prefer and I am going to show it to you now. It is much easier -- in my opinion -- that what you've just done thus far.
The general heuristic is divide by 16, multiple remainder by 16, convert to hex.
158 / 16 = 9.875
Take the remainder (.875) and multiply it by 16 and round up if necessary.
.875 * 16 = 14.
This is the digits place and 14 in hexadecimal is E: 0xXE
Take the number without the remainder from the previous step, which is 9 and divide by 16, but since 9/16 = 0, move the nine over: 0x9E
The number 15810 is 9E16, 0x9E or 9Eh hexadecimal. Isn't that much easier?
Convert denery into octal
Because we've covered that odd base-7 earlier, and it's just a bit of the same thing with using eights instead of sevens I'll leave this section as an exercise for the reader. Convert 15810 into base-8.
Step 6: From Binary to Hex and Back Again
Now the truly useful (programming-wise) conversions can be done, with all this base nonsense under our belts now. And funny enough, it just keeps getting easier and easier.
Convert from hexadecimal to binary
Let's convert a hex number, say, 0xFD90 into it's binary equivalent. The key here is to decode four bits at a time from the hexadecimal into the binary target. Look at this.
Take the first digit of hex: F
F = 16 = 1111Take the second digit of hex: D
D = 13 = 1101Take the third digit of hex: 9
9 = 9 = 1001And the final digit: 0
0 = 0 = 0000
Put them together in order from left to right and you get:
1111 1101 1001 0000 or 11111101100100002 binary.See? You don't really get any easier than that. Well, actually it does. Check out the process in reverse.
Convert from binary into hexadecimal
Convert the binary number 10011101000101012 into hexadecimal.
Again, decode 4 bits at a time. Break up the binary number into nibbles (4-bits).
1001 1101 0001 0101
1001 = 9
1101 = 13 = D
0001 = 1 = 1
0101 = 5 = 5
The binary number 10011101000101012 is 0x9D15
Step 7: Conclusion
In this instructable, I've briefly discussed bases and their meanings. Further, I've attempted to impart upon you -- the reader -- some general heuristics that you can take with you into your next programming or lateral thinking puzzle to help you convert between numbers of any base into numbers of any base, and back again, if needed.
As always, I am open to your suggestions and comments on how to make this instructable and any of my 'ibles better. If you like my instructable, please rate it!