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

Feb 13, 2017 at 7:33am
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.
Feb 13, 2017 at 7:50am
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.
Feb 26, 2017 at 3:10pm
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 Feb 26, 2017 at 3:13pm
Feb 26, 2017 at 3:22pm
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.

Feb 26, 2017 at 3:29pm
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 :(
Feb 26, 2017 at 3:31pm
My instructor told me to write the function Pow and I can't use pow.
Feb 26, 2017 at 3:32pm
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 Feb 26, 2017 at 3:33pm
Feb 26, 2017 at 3:34pm
Hexa: 0x1FA5CC99
2781610137

It is still wrong...
Feb 26, 2017 at 3:39pm
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
Feb 26, 2017 at 3:53pm
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];


Feb 26, 2017 at 3:57pm
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;
}

Feb 26, 2017 at 4:05pm
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.
Feb 26, 2017 at 5:10pm
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.