1

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.

Markus Hedlund
  • 23,374
  • 22
  • 80
  • 109
  • 3
    Any particular part, or should we just read through it for you? – Ignacio Vazquez-Abrams Jan 18 '11 at 20:50
  • 1
    Do you know what base62 is...? Say, compared to base16 as a clue? – gbn Jan 18 '11 at 20:52
  • Haha, the loop foremost. I know what `log10` and `pow` functions does of course, but not how this converter works. If were to write this, I would probably have used the modulo operator (not sure if that'd worked though). – Markus Hedlund Jan 18 '11 at 20:56
  • 1
    I'm not sure why this would be necessary instead of http://www.php.net/manual/en/function.base-convert.php – Jamie Hurst Jan 18 '11 at 20:57
  • @Znarkus: `log10` performs a `log` with a base of 10. `pow` does a power raise, so x^y would be `pow($x, $y);` – Josh K Jan 18 '11 at 20:58
  • @jamie `Both frombase and tobase have to be between 2 and 36, inclusive.` @Josh thanks, but `I know what log10 and pow functions does` ;-) – Markus Hedlund Jan 18 '11 at 21:01

4 Answers4

5

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;
}
Alix Axel
  • 151,645
  • 95
  • 393
  • 500
  • 2
    Any reason you're concating the string backwards and then reversing it? `$string = self::$_characters[$num % $base] . $string;` would otherwise make for a more readable code imo – Markus Hedlund Jan 19 '11 at 09:36
  • @Znarkus: Well spoted! I was biased by the base x to 10 code when I coded this. – Alix Axel Jan 19 '11 at 15:24
1

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.

Roger Halliburton
  • 1,965
  • 3
  • 14
  • 18
1

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
psmay
  • 1,001
  • 7
  • 17
0

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 
}
Josh K
  • 28,364
  • 20
  • 86
  • 132
  • Why start at `floor(log10($num) / log10($base))`, what does `log10($num) / log10($base)` calculate? Sorry if I was unclear: I don't understand the algorithm, I *understand* the PHP :) – Markus Hedlund Jan 18 '11 at 21:04
  • Hehe, you actually explained everything but what I didn't understand :p – Markus Hedlund Jan 18 '11 at 21:07
  • 1
    (log-base-10 N) / (log-base-10 B) = (log-base-B N). It's the low estimate of the number of base-B digits necessary to express N. – psmay Jan 18 '11 at 21:08
  • @Znarkus: @psmay is correct. You want to start at the low estimate of how many characters you need to define N. – Josh K Jan 18 '11 at 23:12
  • Anyone care to explain the DV? – Josh K Jan 19 '11 at 14:14