patternMinor
Is there a more efficient way to do Base 32 encoding/decoding than this?
Viewed 0 times
thisthanmorewayefficientdecodingencodingtherebase
Problem
This journey started with a quest to create the shortest possible case-insensitive verification number. Based on the answers there, I worked out a Classic ASP/VBScript implementation of Crockford's Base32 Encoding and it has served me well so far.
Out of semi-idle curiosity, I was wondering if there was a way to further improve the performance. To be clear: it works, and it runs more than fast enough. I am planning to use it more extensively and since I never heard back on a better way, I was hoping for a second set of eyes to say "yes, it's as good as it's going to get" or "here's how to make it more awesome" or whatever.
So you don't have to go back to the latter Stack Overflow question to see the code, here it is:
Out of semi-idle curiosity, I was wondering if there was a way to further improve the performance. To be clear: it works, and it runs more than fast enough. I am planning to use it more extensively and since I never heard back on a better way, I was hoping for a second set of eyes to say "yes, it's as good as it's going to get" or "here's how to make it more awesome" or whatever.
So you don't have to go back to the latter Stack Overflow question to see the code, here it is:
'Base32 encoding functions for shorter, less confusing verification numbers
Const kBase32Digits = "0123456789abcdefghjkmnpqrstvwxyz"
Function ToBase32(ByVal lInput)
Dim lModulo, sTemp
Do Until lInput = 0
lModulo = lInput Mod 32
sTemp = Mid(kBase32Digits, lModulo + 1, 1) & sTemp
lInput = lInput \ 32
Loop
ToBase32 = sTemp
End Function
Function FromBase32(ByVal sInput)
Dim sTemp, sR, i,iY,lLen, zMultiplier
sTemp = LCase(sInput)
sTemp = Replace(sTemp,"o","0")
sTemp = Replace(sTemp,"i","1")
sTemp = Replace(sTemp,"l","1")
sTemp = Replace(sTemp,"u","v")
zMultiplier = 1
lLen = Len(sTemp)
For i = lLen To 1 Step -1
sR = Mid(sTemp, i, 1)
iY = InStr(1, kBase32Digits, sR, vbTextCompare) - 1
FromBase32 = FromBase32 + iY * zMultiplier
zMultiplier = zMultiplier * 32
Next
End FunctionSolution
If you really want to chase those milliseconds then I would try following:
1) I consider division operations as slow so I would avoid using two divisions if it can be replaced with one division and some easier operation:
2) In some other language I would use bit shift of course instead of diviosion/multiply. But as far as I got vbscript doesn't have bit shifting operators.
3) Your
P.S. of course I haven't measured anything, I do not even know vbscript, just wanted to give you an idea on what can be changed.
P.P.S.: My second point doesn't take into account that there is a chance that VBScript interpreter will do such an optimization for you.
1) I consider division operations as slow so I would avoid using two divisions if it can be replaced with one division and some easier operation:
Function ToBase32(ByVal lInput)
Dim lModulo, sTemp, lNextInput
Do Until lInput = 0
lNextInput = lInput \ 32
lModulo = lInput - 32 * lNextInput
sTemp = Mid(kBase32Digits, lModulo + 1, 1) & sTemp
lInput = lNextInput
Loop
ToBase32 = sTemp
End Function2) In some other language I would use bit shift of course instead of diviosion/multiply. But as far as I got vbscript doesn't have bit shifting operators.
3) Your
FromBase32 method doesn't look optimal to me at all. I would replace those Replace and InStr calls with array of integers for letter chars. This array will contains corresponding base 32 numbers for chars. And you will be able to translate letter into number using array indexing accessor which is much faster operation than looking for a character in a string. Some pseudocode showing how to convert character sR into number: Dim sR;
// defining an array:
Dim charArray = [ 10, // 'a' char
11, // 'b' char
...
17, // 'h'
1 , // 'i' !!
...
0 , // 'o'
...];
Dim lNumber;
if (sR >= 'a' && sR <= 'z')
lNumber = charArray[sR - 'a'];
else // it is digit
lNumber = sR - '0' // in most languages I know this will convert '1' char into 1 integerP.S. of course I haven't measured anything, I do not even know vbscript, just wanted to give you an idea on what can be changed.
P.P.S.: My second point doesn't take into account that there is a chance that VBScript interpreter will do such an optimization for you.
Code Snippets
Function ToBase32(ByVal lInput)
Dim lModulo, sTemp, lNextInput
Do Until lInput = 0
lNextInput = lInput \ 32
lModulo = lInput - 32 * lNextInput
sTemp = Mid(kBase32Digits, lModulo + 1, 1) & sTemp
lInput = lNextInput
Loop
ToBase32 = sTemp
End FunctionDim sR;
// defining an array:
Dim charArray = [ 10, // 'a' char
11, // 'b' char
...
17, // 'h'
1 , // 'i' !!
...
0 , // 'o'
...];
Dim lNumber;
if (sR >= 'a' && sR <= 'z')
lNumber = charArray[sR - 'a'];
else // it is digit
lNumber = sR - '0' // in most languages I know this will convert '1' char into 1 integerContext
StackExchange Code Review Q#2029, answer score: 5
Revisions (0)
No revisions yet.