Base36 Encoder/Decoder in C#

For a project I am working on I needed a way to convert long numbers into Base 36 numbers. Base 36 uses number 0 to 9 and letters a to z, but is not case sensitive (there is no differentiation between uppercase and lowercase letters), which makes it perfect for being transferred over the telephone.

As the .net Framework does not have a Built-In function for Base 36, I've converted the one from the Wikipedia Article to C#. Note that the "Reverse" function could as well be an extension Method if you use a more recent .net Framework, but to keep it simple it's an instance method here. You can test it against the examples in the Wikipedia article if you want to verify it.

By the way, I've chosen lowercase letters here, but if you want, you can just make them uppercase. Also, note that these functions work with a long, not with a double, so no floating point action here.

private long base36decode(string inputString)
{
    string clist = "0123456789abcdefghijklmnopqrstuvwxyz";

    inputString = Reverse(inputString.ToLower());
    long result = 0;
    int pos = 0;
    foreach (char c in inputString)
    {
        result += clist.IndexOf(c) * (long)Math.Pow(36, pos);
        pos++;
    }
    return result;
}

private string base36encode(long inputNumber)
{
    char[] clist = new char[] { '0', '1', '2', '3', '4',
                                '5', '6', '7', '8', '9',
                                'a', 'b', 'c', 'd', 'e',
                                'f', 'g', 'h', 'i', 'j',
                                'k', 'l', 'm', 'n', 'o',
                                'p', 'q', 'r', 's', 't',
                                'u', 'v', 'w', 'x', 'y',
                                'z' };

    StringBuilder sb = new StringBuilder();
    while (inputNumber != 0)
    {
        sb.Append(clist[inputNumber % 36]);
        inputNumber /= 36;
    }
    return Reverse(sb.ToString());
}

private string Reverse(string input)
{
    Stack<char> resultStack = new Stack<char>();
    foreach (char c in input)
    {
        resultStack.Push(c);
    }

    StringBuilder sb = new StringBuilder();
    while (resultStack.Count > 0)
    {
        sb.Append(resultStack.Pop());
    }
    return sb.ToString();
}

Addendum: There is a slightly easier/less redundant way to keep the two clist's:

private const string clist = "0123456789abcdefghijklmnopqrstuvwxyz";

private long base36decode(string inputString)
{
    // Remove the declaration of clist inside this function, leave the rest as is.
}

private string base36encode(long inputNumber)
{
    char[] clistarr = clist.ToCharArray();
    // replace the references to clist with clistarr for the rest of the function
}

Comments (3)

nwisoftNovember 6th, 2008 at 11:15

//Thank you for this good sample.
//You just need to Trim start zeros to avoid wrong result : "0H" must return 17.

private const string CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

static public long Decode(string value)
{
List database = new List(CHARACTERS);
List tmp = new List(value.ToUpper().TrimStart(new char[] { '0' }).ToCharArray());
tmp.Reverse();

long number = 0;
int index = 0;
foreach (char character in tmp)
{
number += database.IndexOf(character) * (long)Math.Pow(36, index);
index++;
}

return number;
}

static private string Encode(long number)
{
List database = new List(CHARACTERS);
List value = new List();
long tmp = number;

while (tmp != 0)
{
value.Add(database[Convert.ToInt32(tmp % 36)]);
tmp /= 36;
}

value.Reverse();
return new string(value.ToArray());
}

Kofi SarfoMarch 19th, 2009 at 17:20

Thanks so much for having posted this. It saved me however long I'd have been fooling around rolling my own implementation :)

Kofi

synhershkoMarch 18th, 2010 at 20:00

Wikipedia had a C# sample, which wasn't working. I updated the code there to use your methods instead, which are working great.

Leave a comment

Your comment