Я кодирую 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 идентификаторов числа, если я использую его, и я не думаю, что этот алгоритм лучше, чем их.
Так, два вопроса:
Требуется всего пара небольших настроек, главные две заключались в том, чтобы сделать алфавит с нулевым индексом, а не с одним индексом, и вычесть остаток от идентификатора перед делением
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
Кстати, проверьте функцию 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");
Может быть, это поможет?