How to convert hexa to base 10 numbers (The hard way)

I searched Google and they all convert numbers using remainder. My instructor does not permit to use module operator when converting hexadecimal numbers. Also, the use of while keyword and std::hex are not permitted also.

However, he did give me a hint : Handle each digit from left to right.
0x1FA5CC99

I need to input hexadecimal numbers as string then return the result as an integer.

How do I do that? Thank you.
1
2
3
4
5
6
A = 10, B = 11, C = 12, D = 13, E = 14, F = 15

exp = 7 6 5 4 3 2 1 0
hex = 1 F A 5 C C 9 9

decimal = 1*16^7 + 15*16^6 + ... + 9*16^1 + 9*16^0

Note that ^ means power/exponent in this scenario, and not XOR.
Here is what I got but the result doesn't really match. So I need help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <iostream>
#include <string>

using namespace std;

unsigned int Pow ( unsigned int base, unsigned int exponent )
{
	unsigned int result;
	if ( exponent == 0 )
	{
		return 1;
	}
	else if ( exponent == 1 )
	{
		return base;
	}
	else
	{
		result = base * base;
		for ( int i = 0; i < exponent; i++ )
		{
		result *= base;
		}
	return result;
	}
}

int hexa_to_num ( char c )
{
	int num;
	switch ( c )
	{
		case '0':
		num = 0;
		break;
		case '1':
		num = 1;
		break;
		case '2':
		num = 2;
		break;
		case '3':
		num = 3;
		break;
		case '4':
		num = 4;
		break;
		case '5':
		num = 5;
		break;
		case '6':
		num = 6;
		break;
		case '7':
		num = 7;
		break;
		case '8':
		num = 8;
		break;
		case '9':
		num = 9;
		break;
		case 'A':
		num = 10;
		break;
		case 'B':
		num = 11;
		break;
		case 'C':
		num = 12;
		break;
		case 'D':
		num = 13;
		break;
		case 'E':
		num = 14;
		break;
		case 'F':
		num = 15;
		break;
		default:
		break;
	}
return num;
} 
unsigned int hexatodecimal ( string hexa )
{
	unsigned int number = 0;
	if ( hexa.size() == 9 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 9 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 8 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 8 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 7 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 7 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 6 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 6 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 5 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 5 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 4 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 4 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 3 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 3 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 2 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 2 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 1 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 1 );
		hexa.erase( hexa.begin() );
	}
	return number;
}

int main ()
{
	string input;
	cout << "Hexa: ";
	cin >> input;
	input.erase( input.begin() );
	input.erase( input.begin() );
	cout << hexatodecimal( input ) << endl;
}


Hexa: 0x1FA5CC99
1556676752
Last edited on
is off by a power.
the least digit, for example, is the value... so if the user puts in
0xc
the answer is just 12, not 12 * 16 which is what you have.

pow(16,0) = 1...

and exponent of 1 isn't a special case, you just loop once. It doesn't hurt anything to do this, but it isn't needed.

and finally, pow is a function in <cmath> ...
you don't need to roll your own unless told to do so.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
	if ( hexa.size() == 9 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 8 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 8 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 7 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 7 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 6 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 6 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 5 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 5 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 4 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 4 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 3 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 3 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 2 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 2 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 1 );
		hexa.erase( hexa.begin() );
	}
	if ( hexa.size() == 1 )
	{
		number += hexa_to_num( hexa[ 0 ] ) * Pow( 16, 0 );
		hexa.erase( hexa.begin() );
	}


Thanks for your reply, I changed it but couldn't really fix the problem. The output changed though :(
My instructor told me to write the function Pow and I can't use pow.
what did you get..?
try working up. does it work for input of 0, 1, a?
if that works, does it work for fd, 12, 00, 10?
...

Last edited on
Hexa: 0x1FA5CC99
2781610137

It is still wrong...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>
#include <stdexcept>

// meets your instructor's specifications: no %, no while, no std::hex
// throws std::invalid_argument if the string is badly formed
// throws std::out_of_range if the converted value would be out of the the range of unsigned long long
unsigned long long hex_to_integer( std::string hex_string )
{
    std::size_t pos = 0 ;
    unsigned long long integer = std::stoull( hex_string, std::addressof(pos), 16 ) ;
    if( pos == hex_string.size() ) return integer ;
    else throw std::invalid_argument( "entire string could not be converted" ) ;
}

int main()
{
    std::cout << hex_to_integer( "0x1FA5CC99" ) << '\n' ; // 530959513
}

http://coliru.stacked-crooked.com/a/e42fcac844de961d
test your power function. does that work? If not,
you could just do this..

//global constant array /lookup table approach
int pow16[] = {1,16,256,4096, ...}; //use calculator to fill in the rest

.. = blah *pow16[power];


You can multiply and divide by 16 using shifts:
x*16 == x<<4
x/16 == x>>4
x%16 == x&4

To convert from hex to decimal, the first one is what matters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::string;    
int main ()
{
    string input;

    while (cin >> input) {
	size_t i=0;
	int output = 0;
	// Does it start with "0x" or "0X"?
	if (input.size() > 2 && input[0] == '0' &&
	    (input[1] == 'x' || input[1] == 'X')) {
	    i = 2;
	}
	for (; i<input.size(); ++i) {
	    char ch = input[i];	// shorthand
	    int val = 0;	// value of current hex digit
	    if (isdigit(ch)) {
		val = ch - '0';
	    } else {
		ch = tolower(ch);
		val = ch - 'a' + 10;
	    }
	    output = (output << 4) + val;  // same as output*16+val
	}
	cout << input << " hex == " << output << " decimal\n";
    }
    return 0;
}

My Pow function does not work for large exponents. How can I fix it?
I have to use Pow to solve the problem that is why my instructor told me to write the Pow function and do not use pow.
I appreciate other solutions but let me know I am on the right track.
No while loops, and no while loops in disguise (ie. no for, no do-while, no goto):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>

static unsigned long long ipow( unsigned int b, unsigned int e ) // return b^e
{
    if( e == 0 ) return 1 ;
    else return b * ipow( b, e-1 ) ;
}

// return value of hex digit hdigit multiplied by 16^e
static unsigned long long cpow16( char hdigit, unsigned int e )
{
    static const std::string hex_digits = "0123456789abcdef" ;

    const auto pos = hex_digits.find( std::tolower(hdigit) ) ;
    if( pos < hex_digits.size() ) return pos * ipow( 16, e ) ;
    else return 0 ; // invalid hex digit
}

// string hex_digits does not contain leading zeroes, does not start with "0X" or "0x"
static unsigned long long convert_helper( std::string hex_digits )
{
    if( hex_digits.empty() ) return 0 ;

    else return cpow16( hex_digits.front(), hex_digits.size()-1 ) + // value of first digit +
                convert_helper( hex_digits.substr(1) ) ; // value of remaining digits
}

unsigned long long hex_to_integer( std::string hex_digits )
{
    // knock off leading "0X", "0x", and strip leading zeroes
    const auto pos = hex_digits.find_first_not_of( "0xX" ) ;
    return pos != std::string::npos ? convert_helper( hex_digits.substr(pos) ) : 0 ;
}

int main()
{
    std::cout << hex_to_integer( "0x001FA5CC99" ) << '\n' ; // 530959513
}

http://coliru.stacked-crooked.com/a/82ae690db2dc96c0
Topic archived. No new replies allowed.