Search code examples
c++radix

Fastest base conversion method?


Right now I'm working on a project which requires an integer to be converted to a base 62 string many times a second. The faster this conversion is completed, the better.

The problem is that I'm having a hard time getting my own base conversion methods to be fast and reliable. If I use strings, it's generally reliable and works well, but it's slow. If I use char arrays, it's generally much faster, but it's also very messy, and unreliable. (It produces heap corruption, comparison of strings that should match return a negative, etc.)

So what's the fastest and most reliable way of converting from a very large integer to a base 62 key? In the future, I plan on utilizing SIMD model code in my application, so is this operation parallelizable at all?

EDIT: This operation is performed several million times a second; as soon as the operation finishes, it begins again as part of a loop, so the faster it runs, the better. The integer being converted is of arbitrary size, and can easily be as large as a 128 bit integer (or larger).

EDIT: This is the function I am currently using.

char* charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int charsetLength = (int)(strlen(charset));

//maxChars is an integer specifying the maximum length of the key
char* currentKey = new char[maxChars];

void integerToKey(unsigned long long location)
{
    unsigned long long num = location;
    int i = 0;

    for(; num > 0; i++)
    {
            currentKey[i] = charset[num % (charsetLength)];
            num /= charsetLength + 1;
    }

    currentKey[i + 1] = '\0';
}

I ripped this out of a class that is part of my application, and some of the code is modified so that it makes sense sans its owning class.


Solution

  • Probably what you want is some version of itoa. Here is a link that shows various versions of itoa with performance tests: http://www.strudel.org.uk/itoa/

    In general, I know of two ways to do this. One way it to perform successive divisions to strip off one digit at a time. Another way is to precompute conversions in "blocks". So you could precompute a block of int to text conversion of size 62^3 then do the digits 3 at a time. Provided you do the memory layout and lookup efficiently this can be slightly faster at runtime but incurs a startup penalty.