views:

333

answers:

7

Hey Guys

Is there a way Convert a number from Base B1 to Base B2 without using any intermediate base.

Ex:

214 from base 5 to base 16 without converting it first to decimal and then decimal to hexadecimal.

--

Thanks

Alok Kr.

+3  A: 

I don't believe there is any "syntactical trick" that allows you to do this for a general base conversion. (A trick that for example allows you to go from the string "214" to the string "3B" without figuring out which integer "214" (base 5) actually corresponds to.)

By that I mean that you necessarily have to know the value of the number you will work with, that is, you need to "parse" the input.

214 in base 5 for instance, would be parsed as 2*52 + 1*5 + 4. By doing such computation you won't get it in decimal form. You'll get it in what ever form your computer decides to store the resulting integer in (probably binary :)

From that point you can easily output the number in, say base 16. (Note that you have not gone via base 10.) As @Lou Franco put it, you've merely gone from string->int->string, instead of string->string.

aioobe
There are some exceptions to this rule. For example, binary to hex could be done without "knowing" the value. Simply swap '0000' for '0', '1111' for 'F' etc... This would require certain mathematical relations between the bases though.
torak
Good point. updated answer a bit :)
aioobe
The most trivial base conversions are between bases N and N^i ; slightly harder is between N^i and N^j (effectively via base N). That's about all the easy conversions you get.
MSalters
+5  A: 

Not sure what you mean. Numbers in those languages aren't in base 10 (if anything, they're base 2) -- when you format the number into a string, you format it with a base.

So, if you have a string representation of a number and you convert it to a number, and then format as a different base -- you aren't converting to base 10 -- you are converting string to int to string.

So, if the question is how do I take a string that represents a number in base B1 and convert it to a string in base B2 without converting it to an int, then I don't see a way to do that easily.

In your example 214 in base 5 is 2*5^2 + 1 * 5 + 4 -- but if you don't want to convert to int, then you don't know that. This number is 59 in base 10, but the computer sees it as 00111011. You can easily format that as Hex. Ultimately, you need to do the divides and multiplies anyway, and store the intermediate results somewhere.

Lou Franco
+1 for `string -> int -> string`.
Andrzej Doyle
It's simpler to generate results least-significant-digit first. Simply divide the original number by the destination base; the remainder is the least-significant digit in the new base. Divide the quotient by the destination base again, and the remainder will be the next-least-significant digit in the new base. Iterate until the quotient is zero and you're done.
supercat
"Simply dividing the original number by the destination base" means I have to convert it to a number. Once I have a number, it's easy to display it in any base.
Lou Franco
A: 

Perhaps you could create a class to represent each base. The class would have a series of fields to represent each digit - for instance a Decimal class would have a units field, a tens field, a hundreds field and so on. Then write mutators to add or subtract one from the value represented by the object (and handle carrying between fields), and an accessor that allows you to check if the value is zero. Create an object in the base of and with the value of the input number (maybe write a method that parses a string?) and an object in the desired base with the value of zero. Then have a loop where you subtract one from the input number and add one to the output number until the input number reaches zero.

If you create the objects by parsing strings, you arguable avoid the problem aioobe points out that you are representing the numbers as binary, although you're arguably using a unary representation. With a little thought you could also make the base class sufficiently generic to handle number of arbitrary bases.

Scott
How very... enterprisey.
Nick Johnson
+2  A: 

Yes and no. Yes if you don't include the fact that the computer does everything in binary (base 2) as another representation. After all, what is the base of value in the following code?

long value = strtol(string, NULL, base);

In some senses value is just an integer, and has no associated base. Combine that with a function to convert from a value to a string representaton in a particular base and you can easily from a string representation in one base to a string representation in another base. Since there's no intermediate string representation there is, is some sense, no intermediate base value.

torak
+1, but `strtol` returns a `long`.
Jens Gustedt
@Jens Gustedt:Oops, changed my mind part way through using atoi so that there would be a base parameter. Thanks.
torak
+6  A: 

This is just an artifact of the fact that we use a decimal system. Therefore, you want to (in your head) think of the "value" of every number in decimal. So you convert everything back to base 10. If you knew how to do division and multiplication in other bases, it would be easy to convert back and forth without using base 10 as an intermediate. Most people however, don't usually do base 5 division/multiplication, and will convert everything back to base 10.

The algorithm is the same though. Divide by the largest power of the new base you can and then divide the remainder by the smaller power and you'll get the new base.

For instance 0x3B to base 5.

(math is in base 16)

3B / 5^2 = 2 remainder 9

9 / 5 = 1 remainder 4

so 0x3B = 214 base 5

If you know how to do non base 10 division, it's simple. However, there is absolutely no reason to learn that, so it's much easier to convert back to base 10 as an intermediate step.

However, there is an easy way to convert between binary and hexidecimal. Just split the number into groups of 4 binary/1 hexadecimal digits, and convert digit by digit.

1111 0000 1100 0001 
   F    0    9    1
demeteloaf
I'm totally agree with this answer, we use decimal as an intermediate base, because we have 10 fingers on our two hands ;-)
PC2st
A: 

Store them as int and then convert when you need to represent them like std::ios_base does.

graham.reeds
+2  A: 

To convert 214base5 to base 16 without an intermediate base, you "just" have to know how to calculate directly in base 5.

First, you need a table of what the base 16 digits are in base 5 (you need a similar table when converting base 10 to base 16, it's just that that one is easier to keep in your head!). This table is easy to create - just start at 0 and increment each base 5 row until you reach f in base 16.

base 16 | base 5
--------+--------
      0 |  0
      1 |  1
      2 |  2
      3 |  3
      4 |  4
      5 | 10
      6 | 11
      7 | 12
      8 | 13
      9 | 14
      a | 20
      b | 21
      c | 22
      d | 23
      e | 24
      f | 30

Now you just need to repeatedly divide by 16 (which is 31base5). We now recall our primary school days, and use long division (if this seems hard, it's because no-one made you learn your times-tables in base 5!):

Step 1:

   ______
31 ) 214

Step 2:

       3 
   ______
31 ) 214 -
     143  

Step 3:

       3 
   _____
31 ) 214 -
     143  
    ----
      21

So the result of 214base5 divided by 31base5 is 3base5 remainder 21base5.

This means that the least significant digit in base16 is 21base5, which you can find in the table is bbase16. The result of the division is 3base5 - if this was greater than 30base5 then we would divide again - but it's not, so this means the most significant digit is (using the table again) 3base16.

So the answer is 214base5 = 3bbase16.

caf