Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

How can I convert a hexadecimal number, for example 0x1A03 to its octal value?

I know that one way is to convert it to decimal and then convert it to octal

0x1A03 = 6659 = 0o15003
  • Is there a simple way to do it without the middle step (conversion to decimal or conversion to binary)?

  • Why do we tend to convert it to Base10 every time?

share|improve this question
    
Does this really fall under "number theory"? I thought number theory was all about the values of numbers, not the notation. Maybe I'm being nitpicky, or maybe I'm just totally wrong. –  MatrixFrog Aug 25 '10 at 8:02

5 Answers 5

up vote 15 down vote accepted

A simpler way is to go through binary (base 2) instead of base 10.

0x1A03 = 0001 1010 0000 0011

Now group the bits in bunches of 3 starting from the right

0 001 101 000 000 011

This gives

0 1 5 0 0 3

Which is your octal representation.

share|improve this answer

There's a fast procedure involving no intermediate representation. You need only four lookup tables totaling 544 entries.

Earlier answers have established that the conversion can be done in blocks of 3 (working right to left). Consider the rightmost block in your example:

0xA03 = 1010 0000 0011 B

You need to break this binary string into four groups of three bits, which I will number 1, 2, 3, 4 from the right to the left:

1: 011 B

2: 000 B

3: 000 B

4: 101 B

The first depends only on the rightmost hex digit 0x3. The second depends only on the two rightmost digits 0x03 (it gets its rightmost bit from the 0x3 and its first two bits from 0x0). The third depends only on the second and third digits 0xA0. The fourth depends only on the third digit 0xA. Whence, you only need to perform the following conversions, each of which can be stored in its own static lookup table:

1: 0x3 --> 03 [16 entries cover all possibilities]

2: (0x0, 0x3) --> 00 [16 * 16 entries]

3: (0xA, 0x0) --> 00 [16 * 16 entries]

4: 0xA --> 5 [16 entries].

Now you repeat with the next block, padding with zeros on the left as needed. Continuing the example, the next block is 0x001:

1: 0x1 --> 01

2: (0x0, 0x1) --> 00.

You can stop here because all the original input has been consumed. The output, working backwards, is 0015003.

This directly answers both parts of the original question: it provides a simple conversion without the middle step and it avoids base 10 (which is rarely used for computer conversion anyway: usually the job is done with bit shifting and masking, essentially a binary operation). In case this procedure still looks too much like the other proposed solutions, please note that it performs absolutely no arithmetic (apart from decrementing pointers to input and output as it proceeds): it takes a string representation (hex) as its input, uses the characters to index its tables, and outputs an octal string.

share|improve this answer
    
Indeed this is great as a computer algorithm; I however got the impression that he was doing these conversions manually, so I suppose an intermediate conversion to binary is still a nicer approach. –  J. M. Aug 26 '10 at 0:08
    
Good point: "simple" depends on your computational model (e.g., Turing machine vs. human being). It's easily done with mental arithmetic by means of the binary conversion. –  whuber Aug 26 '10 at 0:58

There is a trick for hex to/from octal because they relate to binary but lets ignore that and consider the general idea (which works for any bases).

Since we want to convert to octal lets start using octal as our number system - as if were always were. So we count like this 1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20,21,22,...

And our multiplication table is:

$$ \begin{array}{|c|c|c|c|c|c|c|} \hline \times & \mathbf 1 & \mathbf 2 & \mathbf 3 & \mathbf 4 & \mathbf 5 & \mathbf 6 & \mathbf 7\\ \hline \mathbf 1 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ \mathbf 2 & 2 & 4 & 6 & 10 & 12 & 14 & 16 \\ \mathbf 3 & 3 & 6 & 11 & 14 & 17 & 22 & 25 \\ \mathbf 4 & 4 & 10 & 14 & 20 & 24 & 30 & 34 \\ \mathbf 5 & 5 & 12 & 17 & 24 & 31 & 36 & 43 \\ \mathbf 6 & 6 & 14 & 22 & 30 & 36 & 44 & 52\\ \mathbf 7 & 7 & 16 & 25 & 34 & 43 & 52 & 61 \\ \hline \end{array} $$

So the hexadecimal digits are $0\text x1 = 1$, $0\text x2 = 2$, $0\text x3 = 3$, $0\text x4 = 4$, $0\text x5 = 5$, $0\text x6 = 6$, $0\text x7 = 7$, $0\text x8 = 10$, $0\text x9 = 11$, $0\text {xA} = 12$, $0\text xB = 13$, $0\text xC = 14$, $0\text xD = 15$, $0\text xE = 16$, $0\text xF = 17$.

Anyway, we want to re-interpret the number 0x1A03 which is equal to $ 20^3 \cdot 1 + 20^2 \cdot 12 + 20 \cdot 0 + 3$. Now we just "do the math", multiply everything out and add it up.

$$ \begin{align} & 20^3 \cdot 1 + 20^2 \cdot 12 + 20 \cdot 0 + 3 \\ =& 10000 + 400 \cdot 12 + 3 \\ =& 10000 + 5000 + 3 \\ =& 10000 + 5000 + 3 \\ =& 15003 \end{align} $$


Now the fact that we have all these zeros suggests there would be a quicker method for these particular bases (normally we would not get so many zeros in our calculations).

share|improve this answer
1  
Please check your result. Should be 0 1 5 0 0 3. –  Américo Tavares Aug 24 '10 at 20:52
    
Thanks for pointing out that arithmetic mistake, I've fixed it now. –  anon Aug 24 '10 at 21:11
1  
You should use $20_8^3$ for example to indicate that those are base 8 numbers: $20_8^3 \cdot 1 + 20_8^2 \cdot 12 + 20_8^1 \cdot 0 + 20_8^0 \cdot 3$ –  Dennis Williamson Aug 24 '10 at 22:36
    
Dennis Williamson, no, I intentionally did not do that. The whole point here is to show that if we use octal as our natural base the 'conversion' calculation is just evaluation and there is nothing special about base 10. –  anon Aug 25 '10 at 6:16
1  
@muad: thanks a lot! –  Lazer Aug 25 '10 at 8:05

I think the easiest way is to go through binary. A hex digit corresponds to 4 bits, an octal digit to 3.

0x1A03 in binary is 0001 1010 0000 0011 (grouped into 4-bit nibbles). If I regroup into 3-bit groups (from the right), I have 001 101 000 000 011. That's octal 0o15003.

share|improve this answer

When you're converting among bases $2^n$, you can often do so more quickly with a comprehensive conversion table. For example, between binary and octal, each block of 3 binary digits will convert to one octal digit: $$\begin{matrix} 000_2=0_8 & 001_2=1_8 & 010_2=2_8 & 011_2=3_8 \\ 100_2=4_8 & 101_2=5_8 & 110_2=6_8 & 111_2=7_8 \end{matrix}$$ Similarly, when converting between binary and hexadecimal, each block of 4 binary digits converts to a single hexadecimal digit. Because of these two facts, each block of 12 (least common multiple of 3 and 4) binary digits is 4 octal digits and 3 hexadecimal digits, so each block of 3 hexadecimal digits can be converted to a block of 4 octal digits. The table for doing hexadecimal<->octal directly is quite large, though, so it's usually simpler to convert to binary as an intermediate form.

It is also possible to do the conversion directly by performing division in octal or hexadecimal, though this can be tricky to get used to.

I think we tend to use decimal as an intermediate form because we are most familiar and comfortable with base 10 (since we generally have 10 fingers and use it most often).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.