php 将数字基数 10 转换为基数 62 (a-zA-Z0-9)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4964197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:23:15  来源:igfitidea点击:

converting a number base 10 to base 62 (a-zA-Z0-9)

phpencodingcharacter-encodingnumericalphanumeric

提问by dynamic

I have a number in base 10. Is there anyway to translate it to a base 62?

我有一个以 10 为基数的数字。无论如何可以将其转换为以 62 为基数的数字?

Example:

例子:

echo convert(12324324);
// returns Yg3 (fantasy example here)

PHP's base_convert()can convert up to base 36.

PHPbase_convert()最多可以转换为 base 36。

回答by Eineki

OLD: A quick and dirty solution can be to use a function like this:

OLD:一个快速而肮脏的解决方案可以是使用这样的函数:

function toChars($number) {
   $res = base_convert($number, 10,26);
   $res = strtr($res,'0123456789','qrstuvxwyz');
   return $res;
}

The base convert translate your number to a base where the digits are 0-9a-p then you get rid of the remaining digits with a quick char substitution.

基数转换将您的数字转换为数字为 0-9a-p 的基数,然后您可以通过快速字符替换去除剩余的数字。

As you may observe, the function is easily reversible.

正如您所观察到的,该函数很容易可逆。

function toNum($number) {
   $res = strtr($number,'qrstuvxwyz','0123456789');
   $res = base_convert($number, 26,10);
   return $res;
}

By the way, what would you use this function for?

顺便问一下,你会用这个功能做什么?



Edit:

编辑:

Based on the question change and on the @jnpcl answer, here is a set of functions that performs the base conversion without using pow and log (they take half the time to complete the tests).

根据问题的变化和@jnpcl 的回答,这里有一组函数可以在不使用 pow 和 log 的情况下执行基本转换(它们需要一半的时间来完成测试)。

The functions work for integer values only.

这些函数仅适用于整数值。

function toBase($num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $r = $num  % $b ;
  $res = $base[$r];
  $q = floor($num/$b);
  while ($q) {
    $r = $q % $b;
    $q =floor($q/$b);
    $res = $base[$r].$res;
  }
  return $res;
}

function to10( $num, $b=62) {
  $base='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $limit = strlen($num);
  $res=strpos($base,$num[0]);
  for($i=1;$i<$limit;$i++) {
    $res = $b * $res + strpos($base,$num[$i]);
  }
  return $res;
}

The test:

考试:

for ($i = 0; $i<1000000; $i++) {
  $x =  toBase($i);
  $y =  to10($x);
  if ($i-$y)
    echo "\n$i -> $x -> $y";
}

回答by drudge

http://us3.php.net/manual/en/function.base-convert.php#52450

http://us3.php.net/manual/en/function.base-convert.php#52450

<?php
// Decimal > Custom
function dec2any( $num, $base=62, $index=false ) {
    if (! $base ) {
        $base = strlen( $index );
    } else if (! $index ) {
        $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
    }
    $out = "";


    // this fix partially breaks when $num=0, but fixes the $num=238328 bug
    // also seems to break (adds a leading zero) at $num=226981 through $num=238327 *shrug*
    // for ( $t = floor( log10( $num ) / log10( $base - 1 ) ); $t >= 0; $t-- ) {

    // original code:
    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;
}
?>

Parameters:

$num- your decimal integer

$base- base to which you wish to convert $num(leave it 0 if you are providing $indexor omit if you're using the default (62))

$index- if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "zyxwvu")

参数:

$num- 你的十进制整数

$base- 您希望转换到的基础$num(如果您提供,则保留为 0,如果您$index使用默认值 (62),则省略)

$index- 如果您希望使用默认数字列表 (0-1a-zA-Z),请省略此选项,否则提供一个字符串(例如:“zyxwvu”)

<?php
// Custom > Decimal
function any2dec( $num, $base=62, $index=false ) {
    if (! $base ) {
        $base = strlen( $index );
    } else if (! $index ) {
        $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, $base );
    }
    $out = 0;
    $len = strlen( $num ) - 1;
    for ( $t = 0; $t <= $len; $t++ ) {
        $out = $out + strpos( $index, substr( $num, $t, 1 ) ) * pow( $base, $len - $t );
    }
    return $out;
}
?>

Parameters:

$num- your custom-based number (string) (ex.: "11011101")

$base- base with which $numwas encoded (leave it 0 if you are providing $indexor omit if you're using default (62))

$index- if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "abcdef")

参数:

$num- 您的自定义号码(字符串)(例如:“11011101”)

$base-$num编码的基数(如果您提供,则保留为 0,如果$index使用默认值 (62),则省略)

$index- 如果您希望使用默认的数字列表 (0-1a-zA-Z),请省略此选项,否则提供一个字符串(例如:“abcdef”)

回答by instanceof me

A simpler (and possibly faster) implementation that does not use pownor log:

一个更简单(并且可能更快)的实现,不使用pownor log

function base62($num) {
  $index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $res = '';
  do {
    $res = $index[$num % 62] . $res;
    $num = intval($num / 62);
  } while ($num);
  return $res;
}

回答by Php'Regex

This function output the same than GNU Multiple Precisionif possible…

如果可能,此函数输出与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

回答by ukautz

For big numbers, you might want to use the PHP BC library

对于大数字,您可能需要使用 PHP BC 库

function intToAny( $num, $base = null, $index = null ) {
    if ( $num <= 0 ) return '0';
    if ( ! $index )
        $index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    if ( ! $base )
        $base = strlen( $index );
    else
        $index = substr( $index, 0, $base );
    $res = '';
    while( $num > 0 ) {
        $char = bcmod( $num, $base );
        $res .= substr( $index, $char, 1 );
        $num = bcsub( $num, $char );
        $num = bcdiv( $num, $base );
    }
    return $res;
}

回答by Doug

function convertBase10ToBase62($num){
    $charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $endChar=$charset[$num%62];
    $rtn="";

    if ( $num == "62" ) { 
        $rtn=$rtn.$charset[1]; 
    } else if ( $num >= 62 ) { 
        $rtn=$rtn.$charset[intval($num/62)%62+1]; 
    }

    $num=intval($num/62);

    while ($num > 61) {
        if ( is_int($num/62) == true ) { 
            $rtn=$rtn.$charset[0]; 
        } else { 
            $rtn=$rtn.$charset[$num%62]; 
        }

        $num=intval($num/62);
    }
    $rtn=$rtn.$endChar;
    echo "\n";
    echo $rtn;

    return $rtn;
}

回答by Patrick

have an array of characters like:

有一个字符数组,如:

$chars = array(
    1 => 'a',
    2 => 'b',
    //....
    27 => 'A',
    28 => 'B'
);

function getCharacter($key)
{
    if(array_key_exists($key, $chars[$key]))
        return $chars[$key];
    return false;
}

function getNumber($char)
{
    return array_search($char, $chars);
}

回答by Tigran Babajanyan

It was hardly tested and works on real big product. Just copy this functions and use. If needed, you can arrange $baseChars sequentially, I need it for blended.

它几乎没有经过测试,适用于真正的大型产品。只需复制此功能并使用。 如果需要,您可以按顺序排列 $baseChars,我需要它进行混合。

    /**
     * decToAny converter
     * 
     * @param integer $num
     * @param string $baseChars
     * @param integer $base
     * @return string
     */
    function decToAny($num, $baseChars = '', $base = 62, $index = false) {

        $baseChars = empty($baseChars) ? 'HbUlYmGoAd0ScKq6Er5PuZp3OsQCh4RfNMtV8kJiLv9yXeI1aWgFj2zTx7DnBw' : $baseChars;
        if (!$base) {
            $base = strlen($index);
        } else if (!$index) {
            $index = substr($baseChars, 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;
    }

Reverse method

逆向法

    /**
     * anyTodec converter
     * 
     * @param string $num
     * @param string $baseChars
     * @param integer $base
     * @return string
     */
    function anyToDec($num, $baseChars = '', $base = 62, $index = false) {

        $baseChars = empty($baseChars) ? 'HbUlYmGoAd0ScKq6Er5PuZp3OsQCh4RfNMtV8kJiLv9yXeI1aWgFj2zTx7DnBw' : $baseChars;
        if (!$base) {
            $base = strlen($index);
        } else if (!$index) {
            $index = substr($baseChars, 0, $base);
        }
        $out = 0;
        $len = strlen($num) - 1;
        for ($t = 0; $t <= $len; $t++) {
            $out = $out + strpos($index, substr($num, $t, 1)) * pow($base, $len - $t);
        }
        return $out;
    }

回答by Vladislav Ross

If you have gmp extension:

如果您有 gmp 扩展名:

gmp_strval(gmp_init($x, 10), 62)

回答by sfg2k

function convertBase10ToBase62($num){
$charset="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$rtn="";

$n=$num;$base=62;
while($n>0){
    $temp=$n%$base;
    $rtn=$charset[$temp].$rtn;
    $n=intval($n/$base);
}
 return $rtn;
}