To convert a number to a different base, we're going to use division.
I'll present the algorithm right now, then explain the intuition behind it.
// num stores a value in base 10
// solution will have digits in an array
index = 0 ;
while ( num != 0 )
{
remainder = num % K ; // assume K > 1
num = num / K ; // integer division
digit[ index ] = remainder ;
index ++ ;
}
| d3 | d2 | d1 | d0 |
| 23 | 22 | 21 | 20 |
| - | - | - | - |
My goal is to represent the number 1310 in binary (i.e., in base 2).
I'm going to fill them in a way that's invalid, but bear
along, because it'll help you understand the algorithm above.
| d3 | d2 | d1 | d0 |
| 23 | 22 | 21 | 20 |
| 0 | 0 | 0 | 1310 |
You wish to exchange 13 US dollars in this new currency. Futhermore, you want to get as few bills as possible (perhaps they charge a smaller fee when this happens).
Initially, however, we start of with the d0 position having the value 13. That's equivalent to 13 1-dollar bills. However, from the previous set of notes, you know that in base 2, each bit position can only have a value between 0 and 1, inclusive. It's not valid to have 13 in d0 (plus, it doesn't minimize the number of bills).
But, for now, let's pretend that it is OK to have it there. What value would we get if we applied the summation formula (where K=2, since this is base 2)?
13 * 20 = 13 * 1
= 13
Of course, this makes sense. We put 13 in the 20 position.
That's the same thing as saying, we want 13 one-dollar bills. Surely,
that adds to 13.
Still, we have this problem that we can't really put 13 in that position.
To fix this problem, we're going to divide 13 by the base. In this case, the base is 2, so we'll divide 13 by 2. Thus, 13/2 = 6. Think of dividing by 2 as a way of counting how many 2-dollar bills we'll need. Dividing by 2 is equivalent to finding how many groups of 2 we have. In this case, after dividing, we have 6 pairs. Of course, there's still one left over. That's the remainder, which is 1.
We can rewrite, in our chart, as:
| d3 | d2 | d1 | d0 |
| 23 | 22 | 21 | 20 |
| 0 | 0 | 610 | 110 |
This means, we have 6 2-dollar bills, and 1 1-dollar bill.
This time, d0 has a value between 0 and 1 (as it should), but d1 = 6. d0 has a valid bit value, but d1 doesn't.
Nevertheless, the summation still works.
(6 * 21) + (1 * 20) = 13 * 1
= 13
Essentially, this says we have six 2-dollar bills and 1 1-dollar bill,
which still adds up to 13 dollars. The total is still correct.
Still, we have violated the rule which says that no digit in base 2 should be greater than 1. Currently, there's a 6 at d1 position. What to do now?
We divide d1 by 2. Intuitively, we're trying to
take the 6 two-dollar bills, make pairs of two-dollar bills, so we can
exchange them for 4-dollar bills. Recall that dividing by 2 is equivalent
to counting how many pairs you have. So, when you divide 6 by 2, you're
trying to count how many groups of 2 you have. If you were dividing by,
say 3, you're trying to count how many groups of 3 you have. (Thus,
13/3 = 3, so you have 3 groups of 3, with 2 leftover).
| d3 | d2 | d1 | d0 |
| 23 | 22 | 21 | 20 |
| 0 | 310 | 0 | 110 |
When you divide 6 by 2, this creates 3 groups of 4. The chart shows that d2=3. This is invalid. Again, the trick is to divide by 2 and exchange 4 dollar bills with 8 dollar bills.
3 / 2 = 1, with a remainder of 3. That means, we can take our 3 4-dollar bills, and create 1 pair of 4-dollar bill, and exchange it for 1 8-dollar bill. However, because there is a remainder of of 1, that means we have a 4-dollar bill left over.
If you use the diagram above, the goal is to make groups of 8
from two groups of 4. You can make one group of 8, but have
one group of 4 left over.
| d3 | d2 | d1 | d0 |
| 23 | 22 | 21 | 20 |
| 110 | 110 | 0 | 110 |
Thus, 1310 = 11012. You can verify this is correct by converting 11012 back to base 10.
Let's trace this out (Look back at the algorithm at the top).
To convert it to base 16, you typically create a string. You convert each element to a character (or a string of one character). If the array element contains a value from 0 to 9, you convert it from "0" to "9". If the value contains a value 10 or greater, you convert it to "A" and above. Obviously, you run into problems if you are using bases higher than 36, but for now, assume you aren't.
Here's an alternate algorithm, that works well if you're
working in binary. It doesn't work well for other bases.
pow = getLargestPowerOfTwo( num ) ;
val = power( 2, pow ) ; // compute 2^pow
while ( val != 0 )
{
if ( num - val >= 0 )
{
num -= val ;
digit[ pow ] = 1 ;
}
else
digit[ pow ] = 0 ;
pow-- ;
val /= 2 ;
}
Let's convert 13 to base 2.
For base 2, pick the greatest power of 2 that is less than or equal to the number you're converting. That is, find the largest N, such that 13 >= 2N.
The greatest power of 2 less than or equal to 13 is 8. 8 is 23 and corresponds to d3.
Subtract the value, but only if the result is 0 or positive. So, 8 subtracted from 13 is 3, which is positive. Place a 1 in d3.
Now, divide 8 by 2 (we're considering d2). This results in 4. Try to subtract 4 from 3. You get -1. So don't subtract. Since it's negative, place a 0 in d2.
Now, divide 4 by 2 (we're considering d1). This results in 2. Try to subtract 2 from 3. You get 1. So subtract. Since it's non-negative, place a 1 in d1.
Now, divide 2 by 2 (we're considering d1). This results in 1. Try to subtract 1 from 1. You get 1. So subtract. Since it's non-negative, place a 1 in d0. Since we're at d0, we're done.
This technique doesn't really work for other bases, but can be modified to do so. The original algorithm presented is easier if you want to work in bases other than 2.
What are you really doing when you divide by K? Essentially, you are trying to create larger and larger powers of K. Notice that the remainder, when dividing by K, is between 0 and K - 1. This is exactly the property we want when we convert to base K.
As practice, pick an arbitrary number in base 10, and convert it to an arbitrary base. To double check your answer, convert it back to base 10 to see if you get the same number as before.