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
converting a number base 10 to base 62 (a-zA-Z0-9)
提问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$index
or 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$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")
参数:
$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 pow
nor log
:
一个更简单(并且可能更快)的实现,不使用pow
nor 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;
}