Number Base Converter, converts numbers from any base to decimal and vice-versa
Keep in mind that if you just want to address some URL in a short way then you don’t really need to read this article. You just have to use one of the multitude of services which provide URL mapping to tiny, generated URLs. Some of those services are: http://tinyurl.com/, http://u.nu/, http://bit.ly/. Just use the one you find the sexiest
What i needed was a way to make URLs on my website as short as possible. I had a huge list of numbered entries each of which had it’s own unique ID and a URL looking like this: mywebsite.com/entries/789465479916 . The best way of making the last number part of the URL as short as possible i found is converting the huge decimal number to the base of 62. Why 62? Because we’ve got 62 alphanumerical symbols there (0-9a-zA-Z) !
The first thing i found after some googling is that php actually provides a function named base_convert() which does what i want. BUT! It doesn’t support base of 62 and really huge numbers. A little disappointed i left this function be and resumed my search of the ideal solution!
In the comments of base_convert() i found a wonderful comment doing nearly exactly what i want. The only bad thing about it was that it didn’t support bug numbers. So i modified the code to use the bcmath php extension which provides support of huge number calculations. Bellow is the modified code.
/**
* BaseConverter provides support of number convertion from any base to
* decimal base and vice-versa.
* The code was originally written here:
* http://www.php.net/manual/en/function.base-convert.php#55204
* and was afterwards modified to support big number calculations.
*
* <b>WARNING!</b> This code requires your PHP installation to have
* enabled BCMath extension. See here for more details:
* http://php.net/manual/en/book.bc.php
*
* @author Yervand Aghababyan ( http://fictionalrealm.com )
* @version 1.0
*/
class BaseConverter {
/**
* Digit list used for conversions to and from base 62
* @var string
*/
private static $digitList = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* Converts $num number from decimal base to any custom base
*
* @param $num Your decimal integer. Should be passed as a string if it's
* bigger than float's maximum value
* @param $base Base to which you wish to convert $num (leave it 0 if you
* are providing $index or omit if you're using the
* default base (62))
* @param $index If you wish to use the default list of digits
* (0-1a-zA-Z), omit this option, otherwise provide
* a string (ex.: "zyxwvu")
* @return string converted number
*/
public static function dec2any($num, $base = 62, $index = false) {
if (!$base) {
$base = strlen ($index);
} else if (!$index) {
$index = substr (self::$digitList, 0, $base);
}
$out = "";
for($t = floor(log( $num, $base)); $t >= 0; $t--) {
$a = bcdiv($num, bcpow ($base, $t ), 0);
$out = $out . substr ($index, $a, 1);
$num = bcsub($num, (bcmul($a, bcpow($base, $t ))));
}
return $out;
}
/**
* Convert number from Custom base to Decimal
* @param $num Your custom-based number (string) (ex.: "11011101")
* @param $base Base with which $num was encoded (leave it 0 if you
* are providing $index or omit if you're using the
* default base (62))
* @param $index If you wish to use the default list of digits
* (0-1a-zA-Z), omit this option, otherwise
* provide a string (ex.: "abcdef")
* @return string decimal number
*/
public static function any2dec($num, $base = 62, $index = false) {
if (! $base) {
$base = strlen ( $index );
} else if (! $index) {
$index = substr ( self::$digitList, 0, $base );
}
$out = 0;
$len = strlen($num) - 1;
for($t = 0; $t <= $len; $t ++) {
$out = bcadd($out, bcmul(strpos($index, substr($num, $t, 1 )), bcpow($base, $len - $t )));
}
return $out;
}
}
With the above code you’re free to do any possible base conversions (dec to hex, hex to bin, bin to dec and so on).
Bellow is an example of the class in work:
// Converting to base 62
echo BaseConverter::dec2any('1'); // 1
echo BaseConverter::dec2any('2'); // 2
echo BaseConverter::dec2any('10'); // a
echo BaseConverter::dec2any('61'); // Z
echo BaseConverter::dec2any('62'); // 10
echo BaseConverter::dec2any('63'); // 11
echo BaseConverter::dec2any('123'); // 1Z
echo BaseConverter::dec2any('78979744647246'); // mqtVtIp8
echo BaseConverter::dec2any('7984516546546463213216'); // 2trjkuyg9ZsJy
echo BaseConverter::dec2any('1646516164654654646464646'); // 8elwAeomcXtCWq
// Converting to decimal numbers
echo BaseConverter::any2dec('10'); // 62
echo BaseConverter::any2dec('mqtVtIp8'); // 78979744647246
echo BaseConverter::any2dec('2trjkuyg9ZsJy'); // 7984516546546463213216
echo BaseConverter::any2dec('8elwAeomcXtCWq'); // 1646516164654654646464646
Also keep in mind that the code requires installed bcmath extension and that if you’re working with big numbers you need to pass those as string to the functions cause php’s rounding them so they’ll fit into a float variable.

This function doesn’t seem to be right.
How come 61 in decimal is ‘Z’ (which is right) and 62 is 10 (wrong) ?
In my conception the number 62 in decimal is Z + 1, which converts to ’00′, hence 63 would be Z + 2, producing ’01′.
Just a thought, I might be wrong though.
well . . . here’s the base i’m using: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
so 62 is 10, 63 – 11 and so on.
what do you think 62 should have been?