Markus Hedlund
Markus Hedlund

Reputation: 24324

Please explain this base 62 PHP conversion function/algorithm

Could anyone please explain the code below? That or point me to some resources shedding some light :)

It converts an integer to a base62 string.

private static $_characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

private static function _convertBase($num)
{
    $base = strlen(self::$_characters);
    $string = '';

    for ($t = floor(log10($num) / log10($base)); $t >= 0; $t--) {
        $a = floor($num / pow($base, $t));
        $string .= substr(self::$_characters, $a, 1);
        $num = $num - ($a * pow($base, $t));
    }

    return $string;
}

Update: What I meant to ask: Could anyone please explain the algorithm below? :) Thanks.

Upvotes: 1

Views: 1892

Answers (4)

Alix Axel
Alix Axel

Reputation: 154653

You're over-complicating:

private static $_characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

private static function _convertBase($num)
{
    $base = strlen(self::$_characters); // 62
    $string = self::$_characters[$num % $base];

    while (($num = intval($num / $base)) > 0)
    {
        $string = self::$_characters[$num % $base] . $string;
    }

    return $string;
}

Upvotes: 5

psmay
psmay

Reputation: 1021

A more pseudocodey version.

// Maps some characters such that
//  0   ->'0'
//  9   ->'9'
//  10  ->'a'
//  35  ->'z'
//  36  ->'A'
//  61  ->'Z'
Let constant characters = List ('0'..'9', 'a'..'z', 'A'..'Z')
Let constant size = length of characters

Function LogBase(number base, number x)
    Return LogBase10(x) / LogBase10(base)

Function LeftMostPosition(unsigned integer message)
    Return Floor(LogBase(size,message))

Function ShiftRight(unsigned integer message, unsigned integer numberOfPositions)
    Return Floor(message / (size to the numberOfPositions power))

Function ShiftLeft(unsigned integer message, unsigned integer numberOfPositions)
    Return message * (size to the numberOfPositions power)

Function Decode(unsigned integer message)
    Let var buffer be a string buffer

    // Runs a number of times equal to LeftMostPosition(message) + 1
    Count position from LeftMostPosition(message) down through 0
        // Get the symbol from the left side of the message
        Let var index = ShiftRight(message, position)
        // Add the decoded character
        To buffer, add characters[index]
        // And then remove it from the incoming message
        Let message = message - ShiftLeft(index, position)

    Return contents of buffer

Upvotes: 1

Roger Halliburton
Roger Halliburton

Reputation: 2021

There is a formula when working with logarithms:

logN(x) = log10(x) / log10(N).

In other words, the log of a number in base N is equal to the log (in base 10) of the number divided by the log (again in base 10) of the base.

So instead of creating a logarithm function for each base, like base 62, you can simply use the native log10() function and scale the numbers accordingly.

And in this particular algorithm, you want to determine how many digits there are, in base 62, for the number you are converting, so you can use that in the "for" loop.

You could, of course, do this is with a while loop without having to calculate log62(n). This is an exercise for the reader.

Upvotes: 1

Josh K
Josh K

Reputation: 28893

Hope this helps.

// Define a set of allowable characters
private static $_characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Function declaration
private static function _convertBase($num)
{
    $base = strlen(self::$_characters); // Count the number of characters available
    $string = '';                       // Initialize an empty string

    // Start the iterator off as (num / character count). Continue until it is zero.
    for ($t = floor(log10($num) / log10($base)); $t >= 0; $t--) {
        $a = floor($num / pow($base, $t));              // Find the numeric (0-$base) position of the corresponding character.
        $string .= substr(self::$_characters, $a, 1);   // Pull that character out and add it to the return string
        $num = $num - ($a * pow($base, $t));            // Subtract it from $num
    }

    return $string;                    // Return the encoded string 
}

Upvotes: -1

Related Questions