Mostafa Bahri
Mostafa Bahri

Reputation: 2644

convert a number from base-10 to another base

I tried the following code to convert a number from base-10 to another base. it works if there is no zero(0) in the destination base. check 79 and 3 and it properly prints 2221 which is correct. now try number 19 and 3, the result would be 21 instead of 201 which indicates something's wrong.

int x, y, a = 0, i, t, j;
cout << "enter two numbers" << endl;
cin >> x >> y; // x as the number in base-10 and x, as the destination base
a = x;
while (x >= y)
{
    t = 1;
    for (i = 0; x > y; i++)
    {
        x /= y;
    }
    cout << x;
    for (j = 0; j < i; j++)
    {
        t *= y;
    }
    a = a - (t*x);
    x = a;
}
cout << x<<endl;

Upvotes: 3

Views: 15310

Answers (4)

R Sahu
R Sahu

Reputation: 206577

Using a recursive function is easier than using a while loop for what you are trying to accomplish.

Here's working program.

#include <iostream>

void printInBase(int x, int y)
{
   if ( x < y )
   {
      std::cout << x;
      return;
   }

   int rem = x%y;
   printInBase(x/y, y);
   std::cout << rem;
}

int main()
{
   int x, y;
   std::cout << "enter two numbers" << std::endl;
   std::cin >> x >> y; // x as the number in base-10 and x, as the destination base
   printInBase(x, y);
   std::cout << '\n';
}

Upvotes: 3

ploni almoni
ploni almoni

Reputation: 1

My answer.

Will also work on floating point numbers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void radix(char *strNum, int base);

int main ()
{
    radix("215.75", 8);
    return 0;
}

void swap(char *a, char *b)
{
    char temp = *a;
    *a = *b;
    *b = temp;
}

void radix(char *strNum, int base)
{
    char res[100]={0}, tmp[100]={0}, floPoint[100]={0}, *p = 0, *q = 0;
    int inum = 0, digitAfterDot = 3;
    float fnum = 0.0;
    if(strchr(strNum, '.'))
    {
        p = strNum + strcspn(strNum, ".");
        fnum = atof(p);
    } 
    inum = atoi(strNum);
    for(p = res; inum; inum /= base, p++)
        *p = (inum % base) + '0';
    *p = 0;
    if(fnum != 0.0)
    {
        p = floPoint;
        *p++ = '.';
        for(fnum *= base; digitAfterDot--; p++, fnum *= base)
        {
            sprintf(tmp, "%f", fnum);
            inum = atoi(tmp);
            fnum -= inum;
            *p = inum + '0';
        }
        *p = 0;
    }
    for(p = res, q = res+strlen(res)-1; p < q; p++, q--)
        swap(p, q);
    strcat(res, floPoint);
    puts(res);
}

Upvotes: 0

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20730

Despite it could work, there is something conceptually wrong in this approach: you are essentially confusing numbers (the subject of arithmetic operations) with their textual representation (the sequence of digits used to represent them).

The type int -by an external point of view- does not have a "base" (int will most likely have a base-2 internal representation, that's functional to the purpose to be manipulated by the arithmetic unit circuitry): it's just a thing to be added, subtracted multilyed, divided, and-ed, xor-ed etc.

When you do cout << a what << do, is convert the a number to a sequence of digit representing it into something readable. By default it happens to do it in base-10 digit represented as ASCII characters ('0'...'9').

What you are doing is convert a number into another number whose decimal representation resemble the base you are mapping. It can work in printing, but there is no arithmetic that can work with it. So int is not a correct representation for them.

What you need is a different text-converter: something that takes an int and another int specifying a base, and spits out the characters to represent your number.

Think to a class like

class based
{
   int n, base;
public:
   based(int num, int base) :n(num), base(base) {}

   friend std::ostream& operator<<(std::ostream& out, const based& x);
};

to be used as

std::cout << bsed(79,3) << ' ' << based(19,3) << std::endl;

Now

std::ostream& operator<<(std::ostream& out, const based& x)
{
    static const size_t N = 8*sizeof(int)+2; //base 2 is the widest, and is 32 or 64 + 2
    char buff[N]; //keep space for sign + base2 + terminator
    size_t X = N-1; //current writing character position
    buff[X] = 0; //terminating char
    --X; //prepare next left character
    int n = x.n; //we will work on n
    bool neg = (n<0); //keep negative sign
    if(neg) n=-n; //and work always with posiotives
    while(n) //we will reduce n down to 0
    {
        int digit = n%x.base; //mod is the last digit
        n /= x.base; //next to the left
        buff[X] = (digit<10)? char(digit+'0'): char(digit-10+'A');
        --X; //next char 
    }
    if(neg) buff[X] = '-'; 
    else ++X; //no sign
    out << buff+X << '(' << x.base << ')'; //the text from the point we reach towards left
    return out; 
}

This will output 2221(3) 201(3).

There is also a more portable way to do char(digit+'0') etc. but considering normal digits, that's not more of what is needed.

Upvotes: 0

genisage
genisage

Reputation: 1169

int x, y, a = 0, i, t, j;
cout << "enter two numbers" << endl;
cin >> x >> y; // x as the number in base-10 and x, as the destination base
a = x;

t = 1;
while (x >= t*y)
{
    t = t * y;
}

while (t)
{
    cout << x/t << ' ';
    x -= t*(x/t);
    t /= y;
}

cout << '\n';

basically you weren't keeping track of what digit you were printing out, and your code can't tell when it would need leading zeroes. You could fix that by printing something like 2*(3^2) + 1*(3^0) or by figuring out how many digits you need in advance as I did in the above code.

Upvotes: 1

Related Questions