Base 2 through 36 conversion

Monkey Forums/Monkey Code/Base 2 through 36 conversion

Goodlookinguy(Posted 2011) [#1]
EDIT (Last day of 2013): I updated the code from it's '09 BlitzMax converted version.

Important Note: Numbers larger than an integer will not convert correctly. This is because the maximum value possible for it to use while converting is 0xFFFFFFFF

EDIT: This is now part of a php based Monkey library at Google Code - http://code.google.com/p/nrgs-monkey-lib/

I've been working on replicating a bunch of php functions into BlitzMax and Monkey. This took me a bit more time than I thought it would, to figure out how to convert between bases. So I'm sharing it here. I figure it has some use, especially for storing or packing large numbers.

I think there may be ways to optimize this function, but I'm not familiar enough with Monkey yet to be sure.


Function
#Rem
Summary: Convert a number between arbitrary bases
Returns a String containing number represented in base tobase. The base in which
number is given is specified in frombase. Both frombase And tobase have To be
between 2 And 36, inclusive. Digits in numbers with a base higher than 10 will
be represented with the letters a-z, with a meaning 10, b meaning 11 And z meaning 35. 
#End
Function BaseConvert:String( number:String, fromBase:Int, toBase:Int )
	If fromBase > 1 And fromBase < 37 And toBase > 1 And toBase < 37
		Local charlist := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		Local inputArray:Int[number.Length]
		Local outputStack := New StringStack()
		Local givenLength := 0
		Local output := ""
		Local outVal := 0
		Local calcVal := 0
		Local calcMod := 0
		Local baseMul := 1
		Local i := 0
		
		number = number.ToUpper()
		
		' So as a quick explanation of what's going on
		' Step one, push the individual values in their decimal equivalent form to the top of the stack
		For i = 0 Until number.Length
			inputArray[i] = charlist.Find(number[i..i + 1])
		Next
		
		' Step two, starting from the rightmost value at 1, start to multiply the value that the
		' decimal value is then multiplied by to get the decimal equivalent of whatever base
		' the inputted number is.
		For i = inputArray.Length() - 1 To 0 Step - 1
			If i < inputArray.Length() - 1
				baseMul *= fromBase
			End
			calcVal += inputArray[i] * baseMul
		Next
		
		' Step three, the math formula that finds the values in decimal form
		While calcVal <> 0
			calcMod = calcVal Mod toBase
			outputStack.Push(calcMod)
			calcVal -= calcMod
			calcVal /= toBase
		Wend
		
		' Step four, pop the value from the stack to get the slice location in the charlist string
		givenLength = outputStack.Length()
		For i = 1 To givenLength
			outVal = Int(String(outputStack.Pop()))
			output += charlist[outVal..outVal + 1]
		Next
		
		If output.Length Then Return output
		Return "0"
	End
	
	Return ""
End


Usage
Function Main:Int()
	Print BaseConvert("ZZVZZX", 36, 10)
	Print "2176595709 <-- Expected"
	Print BaseConvert("FFFFFFFF", 16, 10)
	Print "4294967295 <-- Expected"
	Print BaseConvert("1295", 10, 36)
	Print "ZZ <-- Expected"
	Print BaseConvert("010", 36, 2)
	Print "100100 <-- Expected"
	Print BaseConvert("000JKH0", 28, 7)
	Print "3453050 <-- Expected"
	Print BaseConvert("00000", 28, 7)
	Print "0 <-- Expected"
	
	Return 0
End