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.
PHP的base_convert()可以转换为base 36。
9 个解决方案
#1
33
a quick and dirty solution can be to use a function like this:
一个快速而肮脏的解决方案可以是使用如下函数:
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 reversable.
正如您所看到的,这个函数很容易反转。
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, a set of functions performs the base conversion without using pow and log (they take half times to complete the tests).
基于问题的改变和@jnpcl的回答,一组函数在不使用pow和log的情况下执行基本转换(完成测试需要花费一半的时间)。
The functions are working 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";
}
#2
7
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 $index or 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.: "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 $num was encoded (leave it 0 if you are providing $index or 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")
#3
3
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;
}
#4
2
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;
}
#5
2
A simpler (and possibly faster) implementation that does not use pow
nor log
:
一种更简单(也可能更快)的实现,不使用pow或log:
function base62($num) {
$index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$res = '';
do {
$res = $index[$num % 62] . $res;
$num = intval($num / 62);
} while ($num);
return $res;
}
#6
2
This function output the same than GNU Multiple Precision if possible…
如果可能,此函数输出与GNU的多重精度相同……
<?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
#7
1
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);
}
#8
1
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;
}
#9
0
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;
}
#1
33
a quick and dirty solution can be to use a function like this:
一个快速而肮脏的解决方案可以是使用如下函数:
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 reversable.
正如您所看到的,这个函数很容易反转。
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, a set of functions performs the base conversion without using pow and log (they take half times to complete the tests).
基于问题的改变和@jnpcl的回答,一组函数在不使用pow和log的情况下执行基本转换(完成测试需要花费一半的时间)。
The functions are working 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";
}
#2
7
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 $index or 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.: "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 $num was encoded (leave it 0 if you are providing $index or 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")
#3
3
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;
}
#4
2
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;
}
#5
2
A simpler (and possibly faster) implementation that does not use pow
nor log
:
一种更简单(也可能更快)的实现,不使用pow或log:
function base62($num) {
$index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$res = '';
do {
$res = $index[$num % 62] . $res;
$num = intval($num / 62);
} while ($num);
return $res;
}
#6
2
This function output the same than GNU Multiple Precision if possible…
如果可能,此函数输出与GNU的多重精度相同……
<?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
#7
1
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);
}
#8
1
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;
}
#9
0
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;
}