• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Simple AnyBase Conversion Library

Status
Not open for further replies.
Just a nice little library I cooked up that can convert a number of base a to a number of base b where the bases can be anything you want from base 2 to base 88.

This would be useful for anyone wanting to make their own save/load code system. Which if you're doing that, you can actually very easily write the save load code to a file on their hard drive which you can then go back and copy/paste back into the game. IMO, thats a little nicer than say, just printing it to the screen and forcing them to type it manually.


JASS:
library baseConverter initializer initBaseConverter
    globals
        private string array digits
        private string result
    
    endglobals
    
    private function discoverLargestExponent takes integer num, integer base returns integer
        local integer i = 0
        
        loop 
            if (num/ (R2I(Pow(I2R(base), I2R(i + 1)))) <= 0) then
                return i
            endif
            
            set i = i + 1
        endloop
        
        return 0
    endfunction

    private function getIntValue takes string char returns integer
        local integer i = 0
    
        loop
            if digits[i] == char then
                return i
            endif
            
            set i = i + 1
        endloop
        
        return 0
    endfunction
    
    public function anyToTen takes string num, integer base returns integer
        local integer retval = 0
        local integer i = StringLength(num) - 1
        local integer power = 0
        
        loop
            exitwhen i < 0

            set retval = retval + getIntValue(SubString(num, i, i + 1)) * R2I(Pow(I2R(base), I2R(power)))
            
            set i = i - 1
            set power = power + 1
        endloop
        
        return retval
    endfunction
    
    public function tenToAny takes integer num, integer base returns string
        local integer array newDigits
        local integer pow = discoverLargestExponent(num, base)
        local integer remain = num
        local integer i = 0
        local integer divValue = 0
        set result = ""
        
        loop
            exitwhen pow - i <= 0
        
            set divValue = R2I(Pow(I2R(base), I2R(pow - i)))
            set newDigits[i] = remain / divValue
            set remain = remain - newDigits[i] * divValue
            
            if (pow - i == 1) then
                set newDigits[i + 1] = remain
            endif
            
            set i = i + 1
        endloop
        
        set i = 0
        
        loop
            exitwhen i > pow
            
            set result = result + digits[newDigits[i]]
            
            set i = i + 1
        endloop
        
        return result
    endfunction
    
    public function anyToAny takes string numX, integer baseX, integer toBase returns string
        local integer baseTen = anyToTen(numX, baseX)
        return tenToAny(baseTen, toBase)
    endfunction
    
    public function initBaseConverter takes nothing returns nothing
        set digits[0] = "0"
        set digits[1] = "1"
        set digits[2] = "2"
        set digits[3] = "3"
        set digits[4] = "4"
        set digits[5] = "5"
        set digits[6] = "6"
        set digits[7] = "7"
        set digits[8] = "8"
        set digits[9] = "9"
        set digits[10] = "a"
        set digits[11] = "b"
        set digits[12] = "c"
        set digits[13] = "d"
        set digits[14] = "e"
        set digits[15] = "f"
        set digits[16] = "g"
        set digits[17] = "h"
        set digits[18] = "i"
        set digits[19] = "j"
        set digits[20] = "k"
        set digits[21] = "l"
        set digits[22] = "m"
        set digits[23] = "n"
        set digits[24] = "o"
        set digits[25] = "p"
        set digits[26] = "q"
        set digits[27] = "r"
        set digits[28] = "s"
        set digits[29] = "t"
        set digits[30] = "u"
        set digits[31] = "v"
        set digits[32] = "w"
        set digits[33] = "x"
        set digits[34] = "y"
        set digits[35] = "z"
        set digits[36] = "A"
        set digits[37] = "B"
        set digits[38] = "C"
        set digits[39] = "D"
        set digits[40] = "E"
        set digits[41] = "F"
        set digits[42] = "G"
        set digits[43] = "H"
        set digits[44] = "I"
        set digits[45] = "J"
        set digits[46] = "K"
        set digits[47] = "L"
        set digits[48] = "M"
        set digits[49] = "N"
        set digits[50] = "O"
        set digits[51] = "P"
        set digits[52] = "Q"
        set digits[53] = "R"
        set digits[54] = "S"
        set digits[55] = "T"
        set digits[56] = "U"
        set digits[57] = "V"
        set digits[58] = "W"
        set digits[59] = "X"
        set digits[60] = "Y"
        set digits[61] = "Z"
        set digits[62] = "!"
        set digits[63] = "@"
        set digits[64] = "#"
        set digits[65] = "$"
        set digits[66] = "%"
        set digits[67] = "^"
        set digits[68] = "&"
        set digits[69] = "*"
        set digits[70] = "("
        set digits[71] = ")"
        set digits[72] = "-"
        set digits[73] = "_"
        set digits[74] = "+"
        set digits[75] = "="
        set digits[76] = "{"
        set digits[77] = "["
        set digits[78] = "}"
        set digits[79] = "]"
        set digits[80] = "/"
        set digits[81] = "?"
        set digits[82] = "."
        set digits[83] = ","
        set digits[84] = "<"
        set digits[85] = ">"
        set digits[86] = "`"
        set digits[87] = "~"
    endfunction
    
endlibrary
 
This is good to show how base conversion works, but I fail to see how it is useful : ). A single large integer is much more efficient than a myriad of smaller integers. This is because you are going to have a lot of wasted space.

Consider two numbers that can go from 0 to 10 in base 10. They can be up to 2 digits. Let's suppose that the values are 10, 10.

With your resource, you would have the following: 1010. Combine the strings. Straightfoward, no?

With a proper resource, you would actually have the following: 120. This is retrieved by combining them into a single large integer with multiplication. The math is 10*11 + 10.

Uh oh o-o. Your resource outputted a code that was a whole 33% larger O_O.

The larger the base you are using, the more wasted space you will get in between numbers. You'd be best off just using binary and then doing a straight up conversion to something like base 64. This isn't to say that binary won't have wasted space too, because believe me, it will. This is to say that converting to a large base and thinking that this will solve all of your space problems is actually going to do the opposite. The larger the base you get with your current method, the worse your space problems become : P. Using a single large integer will not have any of these problems. It can freely use an extremely large base without introducing any space between values.


Another point I'd like to make is that if you try to expand out your current division algorithm to a much larger number, you will get overflows, which will end up giving you the wrong answer. The remainder itself needs to also be able to have a lot of digits. Furthermore, the algorithm will not work because you will not be able to divide two large numbers with the "/" operation. They will be arrays of digits. You will have to figure out how to do it on a much smaller scale and then progressively divide them out.


I have an interactive tutorial that covers how to create a save/load system. It does not teach you how to use a save/load system, but rather how to make one. It will teach you the math and some useful techniques. It won't necessarily teach you the algorithms that you need to come up with to do said math : p. It will also show you how the techniques, when used properly, can reduce code size. If you are interested, I can link this tutorial to you. Alternatively, you can click "My Resources" in my signature, go to jass, and then tutorials. It should be there. To run through the tutorial, play the map; do not look at it in World Editor.
 
Last edited:
This is good to show how base conversion works, but I fail to see how it is useful : ). A single large integer is much more efficient than a myriad of smaller integers. This is because you are going to have a lot of wasted space.

Consider two numbers that can go from 0 to 10 in base 10. They can be up to 2 digits. Let's suppose that the values are 10, 10.

With your resource, you would have the following: 1010. Combine the strings. Straightfoward, no?

With a proper resource, you would actually have the following: 120. This is retrieved by combining them into a single large integer with multiplication. The math is 10*11 + 10.

Uh oh o-o. Your resource outputted a code that was a whole 33% larger O_O.

The larger the base you are using, the more wasted space you will get in between numbers. You'd be best off just using binary and then doing a straight up conversion to something like base 64. This isn't to say that binary won't have wasted space too, because believe me, it will. This is to say that converting to a large base and thinking that this will solve all of your space problems is actually going to do the opposite. The larger the base you get with your current method, the worse your space problems become : P. Using a single large integer will not have any of these problems. It can freely use an extremely large base without introducing any space between values.


Another point I'd like to make is that if you try to expand out your current division algorithm to a much larger number, you will get overflows, which will end up giving you the wrong answer. The remainder itself needs to also be able to have a lot of digits. Furthermore, the algorithm will not work because you will not be able to divide two large numbers with the "/" operation. They will be arrays of digits. You will have to figure out how to do it on a much smaller scale and then progressively divide them out.


I have an interactive tutorial that covers how to create a save/load system. It does not teach you how to use a save/load system, but rather how to make one. It will teach you the math and some useful techniques. It won't necessarily teach you the algorithms that you need to come up with to do said math : p. It will also show you how the techniques, when used properly, can reduce code size. If you are interested, I can link this tutorial to you. Alternatively, you can click "My Resources" in my signature, go to jass, and then tutorials. It should be there. To run through the tutorial, play the map; do not look at it in World Editor.

You are correct this library is worthless on numbers of BigInt datatype but I've tested it on any large standard integers. And you're also right, the larger base loses effectiveness unless the numbers are much larger. For example, you can even make base 1000 if you use digits that are two characters long. But this is highly worthless unless your numbers range in the many trillions.

Although, I thank you for your insight. This library is meant simply for condensing down simple integer values.
 
Status
Not open for further replies.
Top