# "what's the fastest way to convert hex to integer in c++?" Code Answer

1

## proposed solutions that render faster than the op's if-else:

• unordered map lookup table

provided that your input strings are always hex numbers you could define a lookup table as an `unordered_map`:

``````std::unordered_map<char, int> table {
{'0', 0}, {'1', 1}, {'2', 2},
{'3', 3}, {'4', 4}, {'5', 5},
{'6', 6}, {'7', 7}, {'8', 8},
{'9', 9}, {'a', 10}, {'a', 10},
{'b', 11}, {'b', 11}, {'c', 12},
{'c', 12}, {'d', 13}, {'d', 13},
{'e', 14}, {'e', 14}, {'f', 15},
{'f', 15}, {'x', 0}, {'x', 0}};

int hextoint(char number) {
return table[(std::size_t)number];
}
``````
• lookup table as user `constexpr` literal (c++14)

or if you want something more faster instead of an `unordered_map` you could use the new c++14 facilities with user literal types and define your table as a literal type at compile time:

``````struct table {
long long tab[128];
constexpr table() : tab {} {
tab['1'] = 1;
tab['2'] = 2;
tab['3'] = 3;
tab['4'] = 4;
tab['5'] = 5;
tab['6'] = 6;
tab['7'] = 7;
tab['8'] = 8;
tab['9'] = 9;
tab['a'] = 10;
tab['a'] = 10;
tab['b'] = 11;
tab['b'] = 11;
tab['c'] = 12;
tab['c'] = 12;
tab['d'] = 13;
tab['d'] = 13;
tab['e'] = 14;
tab['e'] = 14;
tab['f'] = 15;
tab['f'] = 15;
}
constexpr long long operator[](char const idx) const { return tab[(std::size_t) idx]; }
} constexpr table;

constexpr int hextoint(char number) {
return table[(std::size_t)number];
}
``````

live demo

## benchmarks:

i ran benchmarks with the code written by nikos athanasiou that was posted recently on isocpp.org as a proposed method for c++ micro-benchmarking.

the algorithms that were compared are:

1. op's original `if-else`:

``````long long hextoint3(char number) {
if(number == '0') return 0;
if(number == '1') return 1;
if(number == '2') return 2;
if(number == '3') return 3;
if(number == '4') return 4;
if(number == '5') return 5;
if(number == '6') return 6;
if(number == '7') return 7;
if(number == '8') return 8;
if(number == '9') return 9;
if(number == 'a' || number == 'a') return 10;
if(number == 'b' || number == 'b') return 11;
if(number == 'c' || number == 'c') return 12;
if(number == 'd' || number == 'd') return 13;
if(number == 'e' || number == 'e') return 14;
if(number == 'f' || number == 'f') return 15;
return 0;
}
``````

2. compact if-else, proposed by christophe:

``````long long hextoint(char number) {
if (number >= '0' && number <= '9') return number - '0';
else if (number >= 'a' && number <= 'f') return number - 'a' + 0x0a;
else if (number >= 'a' && number <= 'f') return number - 'a' + 0x0a;
else return 0;
}
``````

3. corrected ternary operator version that handles also capital letter inputs, proposed by g24l:

``````long long hextoint(char in) {
int const x = in;
return (x <= 57)? x - 48 : (x <= 70)? (x - 65) + 0x0a : (x - 97) + 0x0a;
}
``````

4. lookup table (`unordered_map`):

``````long long hextoint(char number) {
return table[(std::size_t)number];
}
``````

where `table` is the unordered map shown previously.

5. lookup table (user `constexpr` literal):

``````long long hextoint(char number) {
return table[(std::size_t)number];
}
``````

where table is user defined literal as shown above.

experimental settings

i defined a function that transforms an input hex string to an integer:

``````long long hexstrtoint(std::string const &str, long long(*f)(char)) {
long long ret = 0;
for(int j(1), i(str.size() - 1); i >= 0; --i, j *= 16) {
ret += (j * f(str[i]));
}
return ret;
}
``````

i also defined a function that populates a vector of strings with random hex strings:

``````std::vector<std::string>
populate_vec(int const n) {
random_device rd;
mt19937 eng{ rd() };
uniform_int_distribution<long long> distr(0, std::numeric_limits<long long>::max() - 1);
std::vector<std::string> out(n);
for(int i(0); i < n; ++i) {
out[i] = int_to_hex(distr(eng));
}
return out;
}
``````

i created vectors populated with 50000, 100000, 150000, 200000 and 250000 random hex strings respectively. then for each algorithm i run 100 experiments and averaged the time results.

compiler was gcc version 5.2 with optimization option `-o3`.

results:

discussion

from the results we can conclude that for these experimental settings the proposed table method out-performs all the other methods. the if-else method is by far the worst where as the `unordered_map` although it wins the if-else method it is significantly slower than the other proposed methods.

code

## edit:

results for method proposed by stgatilov, with bitwise operations:

``````long long hextoint(char x) {
int b = uint8_t(x);
int maskletter = (('9' - b) >> 31);
int masksmall = (('z' - b) >> 31);
int offset = '0' + (maskletter & int('a' - '0' - 10)) + (masksmall & int('a' - 'a'));
return b - offset;
}
``````

edit:

i also tested the original code from g24l against the table method:

``````long long hextoint(char in) {
long long const x = in;
return x < 58? x - 48 : x - 87;
}
``````

note that this method doesn't handle capital letters `a`, `b`, `c`, `d`, `e` and `f`.

results:

still the table method renders faster.

By chamberlainpi on January 15 2022