PHP – Как base_convert () до базы 62

Мне нужна base_convert() которая работает с базы 2 до базы 62, но мне не хватает математики, которую мне нужно использовать, я знаю, что из-за ограничений PHP мне нужно использовать bcmath, и это нормально.

Такие функции, как эти, преобразуют число от базы 10 к другой базе до 62, но я хочу реализовать те же функции base_convert() , например: только одна функция, которая может конвертировать между произвольными базами.

Я нашел функцию, которая, кажется, делает это , но это дает мне ощущение наличия избыточного и медленного кода, и я хотел бы немного подстроить его, если бы я знал немецкий, чего я не знаю. знак равно

Вот более читаемая версия функции:

 function bc_base_convert($value, $quellformat, $zielformat) { $vorrat = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; if (min($quellformat, $zielformat) < 2) { trigger_error('Bad Format min: 2', E_USER_ERROR); } if (max($quellformat, $zielformat) > strlen($vorrat)) { trigger_error('Bad Format max: ' . strlen($vorrat), E_USER_ERROR); } $dezi = '0'; $level = 0; $result = ''; $value = trim(strval($value), "\r\n\t +"); $vorzeichen = '-' === $value{0} ? '-' : ''; $value = ltrim($value, "-0"); $len = strlen($value); for ($i = 0; $i < $len; $i++) { $wert = strpos($vorrat, $value{$len - 1 - $i}); if (FALSE === $wert) { trigger_error('Bad Char in input 1', E_USER_ERROR); } if ($wert >= $quellformat) { trigger_error('Bad Char in input 2', E_USER_ERROR); } $dezi = bcadd($dezi, bcmul(bcpow($quellformat, $i), $wert)); } if (10 == $zielformat) { return $vorzeichen . $dezi; // abkürzung } while (1 !== bccomp(bcpow($zielformat, $level++), $dezi)); for ($i = $level - 2; $i >= 0; $i--) { $factor = bcpow($zielformat, $i); $zahl = bcdiv($dezi, $factor, 0); $dezi = bcmod($dezi, $factor); $result .= $vorrat{$zahl}; } $result = empty($result) ? '0' : $result; return $vorzeichen . $result; } 

Может ли кто-нибудь объяснить мне вышеупомянутую функцию или дать мне некоторые огни о процессе прямого преобразования между произвольными основаниями?

Solutions Collecting From Web of "PHP – Как base_convert () до базы 62"

Начиная с PHP 5.3.2 и bc_math и gmp теперь поддерживают базы до 62, поэтому вы можете просто сделать:

 echo gmp_strval(gmp_init($mynumber, $srcbase), $destbase); 

или эквивалент bc_math.

Пожалуйста, не спрашивайте меня, откуда я его взял, я просто помню, что его основали некоторые примеры, которые я нашел в Интернете …

  function charset_base_convert ($numstring, $fromcharset, $tocharset) { $frombase=strlen($fromcharset); $tobase=strlen($tocharset); $chars = $fromcharset; $tostring = $tocharset; $length = strlen($numstring); $result = ''; for ($i = 0; $i < $length; $i++) { $number[$i] = strpos($chars, $numstring{$i}); } do { $divide = 0; $newlen = 0; for ($i = 0; $i < $length; $i++) { $divide = $divide * $frombase + $number[$i]; if ($divide >= $tobase) { $number[$newlen++] = (int)($divide / $tobase); $divide = $divide % $tobase; } elseif ($newlen > 0) { $number[$newlen++] = 0; } } $length = $newlen; $result = $tostring{$divide} . $result; } while ($newlen != 0); return $result; } 

Самый простой подход для любых задач перевода, начиная с числовой базы и заканчивая человеческими языками, – это переводить через промежуточный формат.

 function bc_base_convert($num, $from, $to) { return bc_convert_to(bc_parse_num($num, $from), $to); } 

Теперь все, что вам нужно написать, – bc_convert_to и bc_parse_num . Если платформа отличает числовые типы, вам нужно принять это за счет. Кроме того, номера с плавающей запятой требуют особого рассмотрения, поскольку число может иметь конечное представление в одном основании, но не другое (например, 1/3 равно 0,1 3, но 0,3333 … 10 и 1/10 10 – 0,0001100110011 … 2 ).

Что касается обобщенного объяснения того, как работает конверсия, подумайте о том, как работают позиционные базовые системы . Цифра формы «a n a n-1 … a 1 a 0 » в базе b представляет число «a n * b n + a n-1 * b n-1 + … + a 1 * b 1 + a 0 * b 0 ". Преобразование в основном работает, оценивая выражение в контексте другой базы β.

Большинство примеров, которые я нашел в Интернете, и в этих ответах используют функции BC Math. Если вы не хотите использовать функции BC Math, вы можете посмотреть эту библиотеку: http://www.lalit.org/lab/base62-php-convert-number-to-base-62-for-short -urls /

  • Он не использует функции BC Math, поэтому работает без использования библиотеки BC Math.
  • Он использует собственные функции base_convert, когда база ниже 36 для более быстрого выполнения.
  • Номер выхода обратно совместим с функцией base base.convert.
  • Может использоваться для преобразования в и из произвольных баз между 2-64.

Я написал об использовании функций BCMath для десятичного / двоичного преобразования здесь: http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/ . Вы можете легко изменить этот код для преобразования в разные базы.

Например, в случае преобразования целых чисел измените процедуры dec2bin_i () и bin2dec_i (). Переименуйте их и добавьте базовый параметр – что-то вроде dec2base_i ($ base, $ decimal_i) и base2dec_i ($ base, $ num_i), измените hardcoded '2' на переменную $ base, преобразуйте числовые остатки в / из символов базы и переименовать переменные.

Теперь, чтобы преобразовать между произвольными базами, используйте десятичное число как промежуточное звено и вызовите обе эти новые функции. Например, преобразуйте базовое число 42 «123» в базу 59, вызывая $ dec = base2dec_i ('42 ',' 123 '), за которым следует $ b59 = dec2base_i (59, $ dec).

(Вы также можете сделать комбинированную функцию, которая делает это за один вызов.)

Эта функция выводит то же, что и GNU Multiple Precision, если это возможно …

 <?php function base_convert_alt($val,$from_base,$to_base){ static $gmp; static $bc; static $gmp62; if ($from_base<37) $val=strtoupper($val); if ($gmp===null) $gmp=function_exists('gmp_init'); if ($gmp62===null) $gmp62=version_compare(PHP_VERSION,'5.3.2')>=0; if ($gmp && ($gmp62 or ($from_base<37 && $to_base<37))) return gmp_strval(gmp_init($val,$from_base),$to_base); if ($bc===null) $bc=function_exists('bcscale'); $range='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($from_base==10) $base_10=$val; else { $n=strlen(($val="$val"))-++$ratio; if ($bc) for($i=$n;$i>-1;($ratio=bcmul($ratio,$from_base)) && $i--) $base_10=bcadd($base_10,bcmul(strpos($range,$val[$i]),$ratio)); else for($i=$n;$i>-1;($ratio*=$from_base) && $i--) $base_10+=strpos($range,$val[$i])*$ratio; } if ($bc) do $result.=$range[bcmod($base_10,$to_base)]; while(($base_10=bcdiv($base_10,$to_base))>=1); else do $result.=$range[$base_10%$to_base]; while(($base_10/=$to_base)>=1); return strrev($to_base<37?strtolower($result):$result); } echo base_convert_alt('2661500360',7,51); // Output Hello в <?php function base_convert_alt($val,$from_base,$to_base){ static $gmp; static $bc; static $gmp62; if ($from_base<37) $val=strtoupper($val); if ($gmp===null) $gmp=function_exists('gmp_init'); if ($gmp62===null) $gmp62=version_compare(PHP_VERSION,'5.3.2')>=0; if ($gmp && ($gmp62 or ($from_base<37 && $to_base<37))) return gmp_strval(gmp_init($val,$from_base),$to_base); if ($bc===null) $bc=function_exists('bcscale'); $range='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($from_base==10) $base_10=$val; else { $n=strlen(($val="$val"))-++$ratio; if ($bc) for($i=$n;$i>-1;($ratio=bcmul($ratio,$from_base)) && $i--) $base_10=bcadd($base_10,bcmul(strpos($range,$val[$i]),$ratio)); else for($i=$n;$i>-1;($ratio*=$from_base) && $i--) $base_10+=strpos($range,$val[$i])*$ratio; } if ($bc) do $result.=$range[bcmod($base_10,$to_base)]; while(($base_10=bcdiv($base_10,$to_base))>=1); else do $result.=$range[$base_10%$to_base]; while(($base_10/=$to_base)>=1); return strrev($to_base<37?strtolower($result):$result); } echo base_convert_alt('2661500360',7,51); // Output Hello в <?php function base_convert_alt($val,$from_base,$to_base){ static $gmp; static $bc; static $gmp62; if ($from_base<37) $val=strtoupper($val); if ($gmp===null) $gmp=function_exists('gmp_init'); if ($gmp62===null) $gmp62=version_compare(PHP_VERSION,'5.3.2')>=0; if ($gmp && ($gmp62 or ($from_base<37 && $to_base<37))) return gmp_strval(gmp_init($val,$from_base),$to_base); if ($bc===null) $bc=function_exists('bcscale'); $range='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($from_base==10) $base_10=$val; else { $n=strlen(($val="$val"))-++$ratio; if ($bc) for($i=$n;$i>-1;($ratio=bcmul($ratio,$from_base)) && $i--) $base_10=bcadd($base_10,bcmul(strpos($range,$val[$i]),$ratio)); else for($i=$n;$i>-1;($ratio*=$from_base) && $i--) $base_10+=strpos($range,$val[$i])*$ratio; } if ($bc) do $result.=$range[bcmod($base_10,$to_base)]; while(($base_10=bcdiv($base_10,$to_base))>=1); else do $result.=$range[$base_10%$to_base]; while(($base_10/=$to_base)>=1); return strrev($to_base<37?strtolower($result):$result); } echo base_convert_alt('2661500360',7,51); // Output Hello