1

I have a method that converts an int to a base60 string (using 0-9, a-z, and A-Z chars), but can't work out how to convert it back again. Here is my method for converting base10 to base60:

public static function toBase60(value:Number):String 
{
    var targetBase:uint = 60;
    value = value.toString().split('.')[0];
    var digits:Array = new Array();
    while (value > 0) 
    {
        digits.push(baseChars[value % targetBase]);
        value = Math.floor(value / targetBase);
    }
    var myResult:String = digits.reverse().join('');
    return myResult;
}

Works well. But how do I get the base60 string back into a base10 int? I happen to be using ActionScript 3, but really, examples in any programming language, generic explanations or sudo code would be great.

Adam Harte
  • 10,369
  • 7
  • 52
  • 85

4 Answers4

4
total = 0;
for each digit (front to back)
  total = total * 60 + digit
Tom Sirgedas
  • 3,208
  • 20
  • 17
  • Shouldn't it be `total**60 * digit`, where `**` is exponentiation? – Adrian Jul 29 '10 at 01:02
  • @Adrian: Nope, for example, 93 [base 60] is 543 [base 10] (9*60+3). Also, 7000 [base 60] is 7*(60**3). My code gets this by multiplying 7 by 60 three times. – Tom Sirgedas Jul 29 '10 at 01:11
2

One way of doing this could be:

    public static function fromBase60(value:String):Number {
        var result:Number = 0;
        var targetBase:uint = 60;
        var digitValue:int = 0;
        for(var i:int = 0, j:int = value.length - 1; j >= 0; i++,j--) {
            digitValue = reverseMap[value.charAt(j)];
            result += Math.pow(targetBase,i) * digitValue; 
        }
        return result;
    }

Looks like you have an array that maps numbers (digits) to characters, so you could build a reverse map upfront and make the lookup easier. With some code like this:

    // add this code to your class
    private static var reverseMap:Object = {};

    private static function buildReverseMap():void {
        var len:int = baseChars.length;
        for(var i:int = 0; i < len; i++) {
            reverseMap[baseChars[i]] = i;
        }
    }

    // initialize the reverse map
    {
        buildReverseMap();
    }

Edit

Alternative implementation, based on algorithm posted by Tom Sirgedas. This avoids calling Math.pow, though I doubt you'll note much difference in practice (performance-wise):

    public static function fromBase60(value:String):Number {
        var result:Number = 0;
        var targetBase:uint = 60;
        var digitValue:int = 0;
        var len:int = value.length;
        for(var i:int = 0; i < len; i++) {
            digitValue = reverseMap[value.charAt(i)];
            result = result * targetBase + digitValue; 
        }
        return result;
    }
Juan Pablo Califano
  • 12,213
  • 5
  • 29
  • 42
0

Assuming you have a function int digit60to10(char digit) that converts [0-9a-zA-Z] into the equivalent decimal value for a single digit, you can do this:

int decimalValue = 0;
foreach digit in digits (most to least significant):
  decimalValue *= 60;
  decimalValue += digit60to10(digit);
Drew Hall
  • 28,429
  • 12
  • 61
  • 81
0

This could give you some problems. But that is not Base 60, it's base 62

Edit Since the above is not a viewed as a valid answer, here is how I converted base 62 <=> 10 in PHP, though there are many methods to do so. http://ken-soft.com/?p=544

I also, explained why I posted that as an answer in the below comment (though I agree it was way too brief) :) sorry.
Edit why is this getting voted down? What I said is true!

Kenny Cason
  • 12,109
  • 11
  • 47
  • 72
  • Well, it may have not been a complete answer, but I felt it was relevant to solving your problem to point out that it if you are using a Base 62 Character set and trying to convert it using Base 60, then your results will be wrong. – Kenny Cason Sep 04 '10 at 01:44
  • Except there's nothing wrong about it, as long as the decoder and encoder understand that the base is 60. There are simply two letters unused. – hobbs Sep 04 '10 at 01:47
  • right, That I agree 100%, (unless you use a base that is higher than the alphabet, which he's not). That's why on the link I posted you will notice that The algorithms never change, only the character set. I was honestly just trying to help him debug the problem, because if you are using a base62 alphabet but converting using base60, that would definitely result in unexpected behavior. – Kenny Cason Sep 04 '10 at 01:57