I need to convert char*
to unsigned long long int
and there is a function called strtoull()
in the C
standard library but it takes to much time. I need to quick conversion between char*
to unsigned long long int
. How can I write my own conversion function which is faster than the standard one?

- 143,097
- 13
- 135
- 256
-
Look at the code for the standard one and try to optimize it? – Martin James Oct 24 '15 at 17:02
-
If this function is too slow, you must be doing a LOT of them, yes? – Martin James Oct 24 '15 at 17:08
-
1"faster" than a standard library function? Can only happen if you give up something. Explain in detail what you want, want you do not need. Chances are this is a weak approach to speed up conversion and optimization effort is better employed elsewhere in the code. – chux - Reinstate Monica Oct 24 '15 at 17:11
-
Actually I'm reading a file which contains key and value pairs. Both key and values are unsigned long long int. I'm using fgets to read lines then I'm parsing a line. This line is char*, so I need to convert this char* key and values into unsigned long long integer. The problem is I have millions of lines and when I profile my code, I saw that strtoull() function took half of the total time. – Oct 24 '15 at 17:18
-
"saw that strtoull() function took half of the total time" in _very_ surprising. Certainly `fgets()` itself must take the lion's share. – chux - Reinstate Monica Oct 24 '15 at 17:20
-
1Read in large L1-cache-size buffers and thread/threadpool off whatever it is that takes ages? – Martin James Oct 24 '15 at 17:22
-
Maybe you could use SSE or AVX registers to vectorize it. Might be kind of hard though since you don't know the length of the string. – chasep255 Oct 24 '15 at 17:25
-
2Rather than the abstract question, post some of the real code. – chux - Reinstate Monica Oct 24 '15 at 17:31
2 Answers
Shortest/fastest code I can think of right now:
unsigned long long strtoull_simple(const char *s) {
unsigned long long sum = 0;
while (*s) {
sum = sum*10 + (*s++ - '0');
}
return sum;
}
No error checking. Profile to find if it improves performance. YMMV.
After accept: Tried a variation that does the initial calculation as unsigned
before continuing on to unsigned long long
. Marginal to negative improvements on my 64-bit machine depending on number set. Suspect it will be faster on machines where unsigned long long
operations are expensive.
unsigned long long strtoull_simple2(const char *s) {
unsigned sumu = 0;
while (*s) {
sumu = sumu*10 + (*s++ - '0');
if (sumu >= (UINT_MAX-10)/10) break; // Break if next loop may overflow
}
unsigned long long sum = sumu;
while (*s) {
sum = sum*10 + (*s++ - '0');
}
return sum;
}
If code knows the length of the string then the following had some performance improvements (5%)
unsigned long long strtoull_2d(const char *s, unsigned len) {
unsigned sumu = 0;
#define INT_MAX_POWER_10 9
if (len > INT_MAX_POWER_10) {
len = INT_MAX_POWER_10;
}
while (len--) {
sumu = sumu * 10 + (*s++ - '0');
}
unsigned long long sum = sumu;
while (*s) {
sum = sum * 10 + (*s++ - '0');
}
return sum;
}
Conclusion: Improvements (I tried 7) on the simple original solution could yield small incremental speed efficiencies, but they become more and more platform and data set dependent. Suggest that programing talent is better applied to the higher level code improvements.

- 143,097
- 13
- 135
- 256
Answer from @soerium modified to use unsigned long long
give better performance than strtoull()
.
unsigned long long fast_atoull(const char *str)
{
unsigned long long val = 0;
while(*str)
{
val = (val << 1) + (val << 3) + (*(str++) - 48);
}
return val;
}

- 1
- 1

- 5,781
- 5
- 31
- 42
-
1The speed-up that @soerium saw using `(val << 1) + (val << 3)` vs. `val*10` demonstrated the weak optimization of that compiler used - not a fundamental faster method. – chux - Reinstate Monica Oct 24 '15 at 17:34
-
1Note: There _is_ a subtle potential slow-down in this answer versus your original. With `val = val*10 + (*str++ - '0');`, the `(*str++ - '0')` is done using `int` math followed by the `unsigned long long` sum with `val*10`. In this latest code: `(val << 1) + (val << 3) + *(str++) - 48;`, notice that the last subtraction is done using `unsigned long long` math. I do not think that can be optimized out - maybe it can. Of course this code could have been `val = (val << 1) + (val << 3) + (*(str++) - 48);`. Often surprising what a small detail can do. – chux - Reinstate Monica Oct 24 '15 at 18:03
-
1@chux, thanks again, I'm surprised how a little detail can affect performance, it nearly `15%` speed up using `(*(str++) - 48)`. – ashiquzzaman33 Oct 24 '15 at 18:20