Base10 к сокращению base64 url

Я кодирую URL shortener функция для проекта, в котором я изучаю php, вот код (btw, я предполагаю это 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;
}

Код взят из этой статьи Wikipedia и адаптирован к php. Моя проблема состоит в том, что, когда я передаю несколько из 64 к функции, я получаю несправедливость (для моей цели) результат, например, 128 возвратов b, который не корректен, это должен был быть aaa, но это слишком длинно для 3-разрядного числа.

Также я начинаю думать, что существует что-то не так в этом коде, если я передаю 1'000'000'000'000 как $id Я получаю nItOq... Я чувствую, что это неправильно, потому что сервис сокращения URL как bit.ly возвращает 6 идентификаторов числа, если я использую его, и я не думаю, что этот алгоритм лучше, чем их.

Так, два вопроса:

  • Вы определяете какую-либо ошибку в вышеупомянутом коде?
  • как справиться 64 - несколько идентификаторов? Я должен просто проигнорировать их и передать следующему?

5
задан Alberto Zaccagni 8 July 2010 в 08:03
поделиться

2 ответа

Требуется всего пара небольших настроек, главные две заключались в том, чтобы сделать алфавит с нулевым индексом, а не с одним индексом, и вычесть остаток от идентификатора перед делением

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

, и вот еще одна модифицированная версия, которая ... ну, мне просто нравится

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

РЕДАКТИРОВАТЬ: сортировка конкатенации такая же, как у OP

11
ответ дан 18 December 2019 в 07:53
поделиться

Кстати, проверьте функцию base_convert() (http://php.net/manual/en/function.base-convert.php):

echo base_convert(1000000000, 10, 36);

36 - самое длинное основание, в которое она может преобразовать. Но в разделе комментариев я нашел вот это:

function dec2any( $num, $base, $index=false ) {
    if (! $base ) {
        $base = strlen( $index );
    } else if (! $index ) {
        $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
    }
    $out = "";
    for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
        $a = floor( $num / pow( $base, $t ) );
        $out = $out . substr( $index, $a, 1 );
        $num = $num - ( $a * pow( $base, $t ) );
    }
    return $out;
}

echo dec2any(1000000000, 64, "_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

Может быть, это поможет?

1
ответ дан 18 December 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: