Xeeshan_65
Xeeshan_65

Reputation: 23

Code to convert decimal to hexadecimal without using arrays

I have this code here and I'm trying to do decimal to hexadecimal conversion without using arrays. It is working pretty much but it gives me wrong answers for values greater than 1000. What am I doing wrong? are there any counter solutions? kindly can anyone give suggestions how to improve this code.

for(int i = num; i > 0; i = i/16)
{
    temp = i % 16;
    (temp < 10) ? temp = temp + 48 : temp = temp + 55;
    num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(int j = num; j > 0; j = j/100)
{   
    ch = j % 100;
    cout << ch;
}

Upvotes: 0

Views: 1607

Answers (4)

zdf
zdf

Reputation: 4818

If this is a homework assignment, it is probably related to the chapter on Recursivity. See a solution below. To understand it, you need to know

  • what a lookup table is
  • what recursion is
  • how to convert a number from one base to another iteratively
  • basic io
void hex_out(unsigned n)
{
  static const char* t = "0123456789abcdef"; // lookup table

  if (!n) // recursion break condition
    return;

  hex_out(n / 16);
  std::cout << t[n % 16];
}

Note that there is no output for zero. This can be solved simply by calling the recursive function from a second function.

You can also add a second parameter, base, so that you can call the function this way:

b_out(123, 10); // decimal
b_out(123, 2); // binary
b_out(123, 8); // octal

Upvotes: 1

Persixty
Persixty

Reputation: 8589

There's a couple of errors in the code. But elements of the approach are clear.

This line sort of works:

(temp < 10) ? temp = temp + 48 : temp = temp + 55;

But is confusing because it's using 48 and 55 as magic numbers! It also may lead to overflow. It's repacking hex digits as decimal character values.

It's also unconventional to use ?: in that way.

Half the trick of radix output is that each digit is n%r followed by n/r but the digits come out 'backwards' for conventional left-right output.

This code reverses the hex digits into another variable then reads them out.

So it avoids any overflow risks. It works with an unsigned value for clarity and a lack of any specification as how to handle negative values.

#include <iostream>

void hex(unsigned num){
    unsigned val=num;
    const unsigned radix=16;
    unsigned temp=0;
    while(val!=0){
        temp=temp*radix+val%radix;
        val/=radix;
    }
    do{
        unsigned digit=temp%16;
        char c=digit<10?'0'+digit:'A'+(digit-10);
        std::cout << c;
        temp/=16;
    }while(temp!=0);
    std::cout << '\n';
}

int main(void) {
    hex(0x23U);
    hex(0x0U);
    hex(0x7U);
    hex(0xABCDU);
    return 0;
}

Expected Output:

23
0
8
ABCD

Arguably it's more obvious what is going on if the middle lines of the first loop are:

while(val!=0){
    temp=(temp<<4)+(val&0b1111);
    val=val>>4;
}

That exposes that we're building temp as blocks of 4 bits of val in reverse order. So the value 0x89AB with be 0xBA98 and is then output in reverse. I've not done that because bitwise operations may not be familiar.

It's a double reverse!

The mapping into characters is done at output to avoid overflow issues. Using character literals like 0 instead of integer literals like 44 is more readable and makes the intention clearer.

Upvotes: 1

amirhm
amirhm

Reputation: 1249

There is a mistake in your code, in the second loop you should exit when j > original num, or set the cumulative sum with non-zero value, I also changed the cumulative num to be long int, rest should be fine.

void tohex(int value){
    long int num = 1;
    char ch = 0;
    int temp = 0;
    for(int i = value; i > 0; i = i/16)
    {
        temp = i % 16;
        (temp < 10) ? temp = temp + 48 : temp = temp + 55;
        num = num * 100 + temp;
    }
    cout<<"Hexadecimal = ";
    for(long int j = num; j > 99; j = j/100)
    {   
        
        ch = j % 100;
        cout << ch;
    }
    cout << endl;
}

Upvotes: 1

Skizz
Skizz

Reputation: 71130

So here's a single loop version of the solution to the problem which should work for any sized integer:-

#include <iostream>
#include <string>

using namespace std;

void main(int argc, char *argv[1])
{
  try
  {
    unsigned
      value = argc == 2 ? stoi(argv[1]) : 64;

    for (unsigned i = numeric_limits<unsigned>::digits; i > 0; i -= 4)
    {
      unsigned
        digit = (value >> (i - 4)) & 0xf;

      cout << (char)((digit < 10) ? digit + 48 : digit + 55);
    }

    cout << endl;
  }
  catch (exception e)
  {
    cout << e.what() << endl;
  }
}

Upvotes: 1

Related Questions