0

I'm trying to write a C program to convert a number given a base, to any other base (Eg. base 2 binary number to base 8, or base 3 to base 16 hex). I've researched this quite a bit, and already read through a similar article, The math behind converting from any base to any base without going through base 10?] but in the explanation given, they utilize an array, which I am not allowed to do for this program.

Without writing a lengthy program with a method for each possible combination of base conversion, I don't see how this is possible without an array to store possible values. I do understand that there is a change of base formula with logs that allows me to change between number bases, but I am unclear how I would apply this, as this formula only gives a decimal number answer, which I would still need to convert.

int log_base_n(int n, int logof)
{
    double logBaseN = log10((double) logof) / log10((double) n);
    return (int) ceil(logBaseN);
}

Here is my binary to decimal conversion which I am trying to use as an intermediate step:

/**
* Convert decimal numbers to binary. Uses a greedy subtraction
* algorithm. Assumes max integer allowed is 2 to 16 power.
*
* @param numberToConvert
*/
void decToBin(int numberToConvert)
{
int power = 16;
double ans = pow(2, power);

if (numberToConvert > ans)
{
    printf("ERROR: Number too large to convert!\n");
    return;
}

while (ans > numberToConvert)
{
    power--;
    ans = pow(2, power);
}

printf("%d", 0);

int i = power;

while (i >= 0)
{

    ans = pow(2, i);
    numberToConvert = numberToConvert - ans;
    printf("%d", 1);
    i--;

    while ((pow(2, i) > numberToConvert) && (i >= 0))
    {
        printf("%d", 0);
        i--;
        ans = pow(2, i);
    }
   }
}

I know Java has a parseInt() method, that does base conversions, but is there something similar I can implement in C without having to write methods for each possible conversion like the one above, while still utilizing a logarithm related idea? Any help would be greatly appreciated.

  • 3
    Note that "base" is only relevant for printing and viewing numbers, the internal representation is always binary. So you might want to read the manual of [`strtol()`](http://man7.org/linux/man-pages/man3/strtol.3.html). – Iharob Al Asimi Sep 16 '18 at 14:23
  • Due to imprecision of `log10()` not returning the exact log, employing `double` functions and math here to do an integer problem is not portable and subject to failures in corner cases. Post more of what you have done to add clarity to the question for better alternatives. – chux - Reinstate Monica Sep 16 '18 at 14:29
  • Your function if implemented correctly should return `char *`, because as I said internal representation is always binary. If you want another representation you need to build a string and use it, because there is no way to alter the internal representation. Read here https://stackoverflow.com/questions/8257714/how-to-convert-an-int-to-string-in-c. – Iharob Al Asimi Sep 16 '18 at 14:32
  • 1
    I suspect that you are having an [XY Problem](http://xyproblem.info), so please tell me what is it that you really need to do. – Iharob Al Asimi Sep 16 '18 at 14:33
  • Thanks @IharobAlAsimi, right now I have a method I created to convert binary to decimal and decimal to binary, I also have a method to convert decimal to hex. I was going to continue creating these separate methods to convert other bases, but saw that using logarithms was recommended in-order to efficiently convert numbers between bases without having to write many methods. I have not yet implemented the log function above, as I don't understand how to. I was planning on converting a number with a given base to decimal, then using log function, then converting back to another base –  Sep 16 '18 at 14:39
  • 1
    If you're not allowed to use arrays, how are you going to input or output numbers in bases greater than 10? As for having to create separate function for each base conversion, you should be able to create one function to convert from *any* base to your intermediate base (binary, decimal, whatever you decide) and another to convert form the intermediate base to the target base. It would be helpful if you posted your decimal to binary conversion functions so we can see what you're doing. – beaker Sep 16 '18 at 14:47
  • Thanks @beaker, I just added my method above –  Sep 16 '18 at 14:51
  • Unfortunately, you've selected an approach that requires that the input be an `int` value in base 10, such that the subtraction operation is defined. What do you intend to do for other input bases? How do you subtract `0x40` from `0x917f`? I think you need to look at the restriction against using arrays again. It doesn't make sense to me. – beaker Sep 16 '18 at 16:03

1 Answers1

1

but is there something similar I can implement in C without having to write methods for each possible conversion like the one above, while still utilizing a logarithm related idea?

Logarithm is a poor choice. The computation of logs in code is not exactly the same as their mathematical counterpart and leads to incorrect output.

The below is a problem should the quotient result in a value just a little higher than a whole number expected value. Of course, log10() is a problem for logof <= 0.

double logBaseN = log10((double) logof) / log10((double) n);
return (int) ceil(logBaseN);

Further, the calculation of log_base_n() is quite unnecessary.

This is an integer problem. Use integer math.


A simply non-array solution "to convert from any base to another base"1 is to use recursion.

void print_int_base(int numberToConvert, int base) {
  // For now, assume numberToConvert >= 0, 2 <= base <= 36
  if (numberToConvert >= base) {
    print_int_base(numberToConvert/base, base);
  }
  int digit = numberToConvert%base;
  int c = digit < 10 ? digit + '0' : digit + 'A';
  putchar(c);
}

Test code

#include <stdio.h>

void print_int_base_test(int numberToConvert, int base) {
  printf("%10d %2d:", numberToConvert, base);
  print_int_base(numberToConvert, base);
  puts("");
}

int main() {
  int numberToConvert = 42;
  for (int base=2; base<=20; base++) {
    print_int_base_test(numberToConvert, base);
  }
}

Output

42  2:101010
42  3:1120
42  4:222
42  5:132
42  6:110
42  7:60
42  8:52
42  9:46
42 10:42
42 11:39
42 12:36
42 13:33
42 14:30
42 15:2M
42 16:2K
42 17:28
42 18:26
42 19:24
42 20:22

1 OP's idea of conversion apparently is to print the int in various bases.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256