随着微博的出现,短网址的应用越来越多了起来。
短网址的关键技术点之一就是把10进制数值转换成62进制。
62进制是利用10个阿拉伯数字、26个英文小写字母和26个英文大写字母来表示数值,以大大减少数值位数。
比如:
62进制 | 10进制 |
ZZZZZ | 916132831 |
ZZZZZZ | 56800235583 |
10进制转换为62进制的函数
/**
* 十进制数转换成62进制
*
* @param integer $num
* @return string
*/
function to62($num) {
$to = 62;
$dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$ret = '';
do {
$ret = $dict[bcmod($num, $to)] . $ret; //bcmod取得高精确度数字的余数。
$num = bcdiv($num, $to); //bcdiv将二个高精确度数字相除。
} while ($num > 0);
return $ret;
}
62进制转换成10进制的函数
/**
* 62进制数转换成十进制数
*
* @param string $num
* @return string
*/
function from62($num) {
$from = 62;
$num = strval($num);
$dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$len = strlen($num);
$dec = 0;
for($i = 0; $i < $len; $i++) {
$pos = strpos($dict, $num[$i]);
$dec = bcadd(bcmul(bcpow($from, $len - $i - 1), $pos), $dec);
}
return $dec;
}
10进制转换成其它任何进制的函数
/**
* 十进制数转换成其它进制
* 可以转换成2-62任何进制
*
* @param integer $num
* @param integer $to
* @return string
*/
function dec_to($num, $to = 62) {
if ($to == 10 || $to > 62 || $to < 2) {
return $num;
}
$dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$ret = '';
do {
$ret = $dict[bcmod($num, $to)] . $ret;
$num = bcdiv($num, $to);
} while ($num > 0);
return $ret;
}
其它任何进制转换成10进制的函数
/**
* 其它进制数转换成十进制数
* 适用2-62的任何进制
*
* @param string $num
* @param integer $from
* @return number
*/
function dec_from($num, $from = 62) {
if ($from == 10 || $from > 62 || $from < 2) {
return $num;
}
$num = strval($num);
$dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$len = strlen($num);
$dec = 0;
for($i = 0; $i < $len; $i++) {
$pos = strpos($dict, $num[$i]);
if ($pos >= $from) {
continue; // 如果出现非法字符,会忽略掉。比如16进制中出现w、x、y、z等
}
$dec = bcadd(bcmul(bcpow($from, $len - $i - 1), $pos), $dec);
}
return $dec;
}
当然,利用上面两个函数,可以进行任何进制之间相互转换:
/**
* 数字的任意进制转换
*
* @param integer|string $number
* @param integer $to 目标进制数
* @param integer $from 源进制数
* @return string
*/
function radix($number, $to = 62, $from = 10) {
// 先转换成10进制
$number = dec_from($number, $from);
// 再转换成目标进制
$number = dec_to($number, $to);
return $number;
}