1、Hash,与运算,映射,位移
MD5来Hash;32位分成四份进行与运算,每份保留30位,这30位分成6段, 每5个一组,算出其整数值,然后映射到准备的62个字符中, 依次进行获得一个6位的短链接地址。
<?php function shorturl($longurl) { //hash私钥(被改进部分) //$shorturlkey = '2rcwzfsefw'; //生成随机字串符(ASCII)(改进部分) //$shorturlkey = ''; //for ($i=0; $i <= 15; $i++) { // $shorturlkey .= chr(mt_rand(33,63)); // $shorturlkey .= chr(mt_rand(64,126)); //} //映射字符(被改进部分) $base62 = 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'); //对映射字符乱序(改进部分) //shuffle($base62); // 利用md5算法方式生成hash值 //$urlhex = hash('md5', $shorturlkey.$longurl); $urlhex = md5($shorturlkey.$longurl); //计算hash后的长度 $urlhexlen = strlen($urlhex); //长度除以8 $subHexLen = $urlhexlen / 8 ; $output = array(); //处理过程 for ($i = 0; $i < $subHexLen; $i++) { // 将这32位分成四份,每一份8个字符,将其视作16进制串与0x3fffffff(30位1)与操作 $subHex = substr($urlhex, $i*8, 8); $idx = 0x3FFFFFFF & (1 * ('0x' . $subHex)); $out = ''; // 这30位分成6段, 每5个一组,算出其整数值,然后映射到62个字符 for ($j = 0; $j < 6; $j++) { $val = 0x0000003D & $idx; $out .= $base62[$val]; $idx = $idx >> 5; } $output[$i] = $out; } //输出生成的四个当中的随机一个(改进部分) //return $output[mt_rand(0,3)]; //(被改进部分) return $output; } ?>来自:http://flyer0126.iteye.com/blog/1591848
不足
经过实际测试(每次生成5K),原始代码重复率很大,一开始可能只有0.000x%,到后来可能上升到0x%。。。
改进
对映射的字符进行随机排位,最后输出的时候只随机输出4个当中的一个,碰撞几率同下
2、纯随机
<?php function shorturl_rand(){ //循环随机,如果要修改位数,直接修改循环条件中的$i小于(n-1)即可 for ($i=0,$b=''; $i <5 ; $i++) { //随机当前位为数字还是小写字母以及大写字母 $a = mt_rand(0,2); //选择器 switch ($a) { case 0: //随机数字 $b .= chr(mt_rand(48,57)); break; case 1: //随机小写字母 $b .= chr(mt_rand(97,122)); break; case 2: //随机大写字母 $b .= chr(mt_rand(65,90)); break; break; default: break; } } return $b ; } ?>纯随机,碰撞几率最低,性能消耗可能是同类中最低。。。