One - One Code All

Blog Content

PHP短链接生成算法

PHP 算法   2011-05-21 17:05:19

最近在开发团购网站的过程中,有个把原文长链接转换成短链接的需求。研究了下,大概有下面几种思路。


一、随机生成

function random($length, $pool = '') 
{ 
	$random = ''; 
	$pool  = 'abcdefghkmnpqrstuvwxyz123456789'; 
	for($i = 0; $i < $length; $i++) 
	{ 
		$j = rand(0,strlen($pool));
		$random .= $pool[$j]; 
	} 

	return $random; 
} 

$a=random(6);
print_r($a);


二、 枚举生成方法


将长网址md5生成32位签名串,分为4段,每段8个字节;
对这四段循环处理,取8个字节,将他看成16进制串与0x3fffffff(30位1)与操作,即超过30位的忽略处理;
这30位分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
总的md5串可以获得4个6位串;取里面的任意一个就可作为这个长url的短url地址;

function shorturl($url) { 
    $base32 = array ( 
        "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","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"  
        ); 

    $hex = md5($url); 
    $output = array(); 

    for ($i = 0; $i < 4; $i++) { 
        $subHex = substr ($hex, $i * 8, 8); 
        echo $subHex;
        //把加密字符按照8位一组16进制与0x3FFFFFFF进行位与运算  
        $int = 0x3FFFFFFF & (1 * ('0x'.$subHex)); 
        echo $int;
        $out = ''; 

        for ($j = 0; $j < 6; $j++) { 
            //把得到的值与0x0000003D进行位与运算,取得字符数组chars索引  
            $val = 0x0000001f & $int; 
            echo $val;
            //把取得的字符相加  
            $out .= $base32[$val]; 
            //每次循环按位右移5位  
            $int = $int >> 5; 
        } 
        $output[] = $out; 
    } 

    return $output; 
} 
$a=shorturl("http://www.baidu.com");
print_r($a);

三、62 位生成方法

function base62($x) 
{ 
    $show= ''; 
    while($x> 0) { 
        $s= $x% 62; 
        if($s> 35) { 
            $s= chr($s+61);       
        } elseif($s> 9 && $s<=35) { 
            $s= chr($s+ 55); 
        } 

        $show.= $s; 
        $x= floor($x/62); 
    } 
    return $show;   
} 

function urlShort($url) 
{ 
    $url= crc32($url); 
    $result= sprintf("%u", $url); 
    return base62($result); 
} 

echo urlShort("http://www.baidu.com/");


四、总结

长网址转短网址,其实就是个62位的转换存储问题,下面来说一下PHP的62进制与10进制互相转化的实现。

/**
 * 十进制数转换成62进制
 *
 * @param integer $num
 * @return string
 */
function from10_to62($num) {
    $to = 62;
    $dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $ret = '';
    do {
        $ret = $dict[bcmod($num, $to)] . $ret;
        $num = bcdiv($num, $to);
    } while ($num > 0);
    return $ret;
}
/**
 * 62进制数转换成十进制数
 *
 * @param string $num
 * @return string
 */
function from62_to10($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;
}



上一篇:PHP基础之bcmod,bcadd
下一篇:PHP实现HTTP断点续传的方法

The minute you think of giving up, think of the reason why you held on so long.