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.
I feel bad because I cant remember where I originally found this, but I have been using this in my code and have found it to be pretty fast. You could modify this to be more efficient in certain places I am sure.
Oh and I feel worse because this is written in Java, but a quick c&p and refactor could get it working in c++
public class BaseConverterUtil {
private static final String baseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String toBase62( int decimalNumber ) {
return fromDecimalToOtherBase( 62, decimalNumber );
}
public static String toBase36( int decimalNumber ) {
return fromDecimalToOtherBase( 36, decimalNumber );
}
public static String toBase16( int decimalNumber ) {
return fromDecimalToOtherBase( 16, decimalNumber );
}
public static String toBase8( int decimalNumber ) {
return fromDecimalToOtherBase( 8, decimalNumber );
}
public static String toBase2( int decimalNumber ) {
return fromDecimalToOtherBase( 2, decimalNumber );
}
public static int fromBase62( String base62Number ) {
return fromOtherBaseToDecimal( 62, base62Number );
}
public static int fromBase36( String base36Number ) {
return fromOtherBaseToDecimal( 36, base36Number );
}
public static int fromBase16( String base16Number ) {
return fromOtherBaseToDecimal( 16, base16Number );
}
public static int fromBase8( String base8Number ) {
return fromOtherBaseToDecimal( 8, base8Number );
}
public static int fromBase2( String base2Number ) {
return fromOtherBaseToDecimal( 2, base2Number );
}
private static String fromDecimalToOtherBase ( int base, int decimalNumber ) {
String tempVal = decimalNumber == 0 ? "0" : "";
int mod = 0;
while( decimalNumber != 0 ) {
mod = decimalNumber % base;
tempVal = baseDigits.substring( mod, mod + 1 ) + tempVal;
decimalNumber = decimalNumber / base;
}
return tempVal;
}
private static int fromOtherBaseToDecimal( int base, String number ) {
int iterator = number.length();
int returnValue = 0;
int multiplier = 1;
while( iterator > 0 ) {
returnValue = returnValue + ( baseDigits.indexOf( number.substring( iterator - 1, iterator ) ) * multiplier );
multiplier = multiplier * base;
--iterator;
}
return returnValue;
}
}