Base10到base64 url​​缩短

Alb*_*gni 5 php url-shortener

我正在编写一个url缩短函数,用于我正在学习php的项目,这里是代码(顺便说一下,我认为这global不是一件好事:P):

$alphabet = array(1 => "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",
                "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","_","-");

function shorten($id){
    global $alphabet;
    $shortenedId = "";
    while($id>0){
        $remainder = $id % 64;
        $id = $id / 64;     
        $shortenedId = $alphabet[$remainder].$shortenedId;
    }
    return $shortenedId;
}
Run Code Online (Sandbox Code Playgroud)

该代码取自这篇维基百科文章 并适用于php.我的问题是,当我通过64到功能我得到一个错误的(我的目的)结果的倍数,例如128回报B的是不正确的,它应该是AAA,但时间太长了3位数.

当然我也会开始觉得有些不对劲这段代码,如果我通过1'000'000'000'000因为$id我得到nItOq ...我觉得这是不对的,因为像bit.ly的URL缩短服务返回6如果我使用它的数字ID,我不认为这个算法比他们更好.

那么,有两个问题:

  • 你发现上面代码中的任何错误?
  • 如何管理64位多重ID?我是否必须忽略它们并转到下一个?

nat*_*han 11

只需要几个小的调整,主要的两个是使字母表为零索引而不是一个索引,并在分割之前从id中减去余数

function shorten($id)
{
    $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
    $shortenedId = '';
    while($id>0) {
        $remainder = $id % 64;
        $id = ($id-$remainder) / 64;     
        $shortenedId = $alphabet{$remainder} . $shortenedId;
    };
    return $shortenedId;
}
Run Code Online (Sandbox Code Playgroud)

这是一个进一步修改过的版本...我很喜欢

function shorten($id, $alphabet='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-')
{
    $base = strlen($alphabet);
    $short = '';
    while($id) {
        $id = ($id-($r=$id%$base))/$base;     
        $short = $alphabet{$r} . $short;
    };
    return $short;
}
Run Code Online (Sandbox Code Playgroud)

编辑:排序串联与OP相同


rgb*_*wed 5

如果您正在寻找相反的函数来获取base64数字并转换为base10,这里有一些PHP基于这个答案中的JavaScript:如何在PHP中将base64转换为base10?

function lengthen($id) {
    $alphabet='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';

    $number=0;
    foreach(str_split($id) as $letter) {
        $number=($number*64) + strpos($alphabet,$letter);
    }
    return $number;
}
Run Code Online (Sandbox Code Playgroud)