我想把一个很大的数字压缩成字母数字[0-9a-zA-Z]。当然,最简单的方法是使用一个名为"base64_encode()"的内置php函数,但我非常贬低这种方法,因为它会产生额外的字符,如"/"answers"="。更重要的是,base64_encode对压缩数字没有任何作用,因为此函数将数字视为字符串。
我曾考虑过另一个名为"base_convert()"的内置函数,但它可以将数字转换为字符集[0-9a-z],使结果更长。
我现在正在使用一种廉价的方式来实现我的目标:
function compress_int($num) {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$result = '';
while( $num ) {
$mod = $num % 52;
$num = intval($num / 52);
$result .= $chars[$mod];
}
return $result;
}
然而,我认为这是非常低效的。所以我非常感谢有人能告诉我一个更好、更高效的方法。^_^
这是我以前为c++应用程序制作的一个。请随意使用。
// $num - the number we want to convert
// $symbols - the chars you want to use e.g. '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
// &$out is a pointer to your $result
function intToBase($num, $symbols, &$out){
// get the radix that we are working with
$radix = strlen($symbols);
$pos = strlen($out)-1;
if($num==0){
// if our number is zero then we can just use the first character of our symbols and we are done.
$out[$pos] = $symbols[0];
}else{
// otherwise we have to loop through and rebase the integer one character at a time.
while ($num > 0) {
// split off one digit
$r = $num % $radix;
// convert it and add it to the char array
$out[$pos] = $symbols[$r];
// subtract what we have added to the compressed string
$num = ($num - $r) / $radix;
$pos--;
}
}
};
简单使用:
$num = 123004954712; //whatever number you want to compress
$result = "";// the result variable we will be writing to
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';// the caracters of our custom base.
intToBase($num, $chars, $result);// the call
// now our $result variable will have the rebased string.
为了完成Goran的答案并节省某人的时间,以下是在转换后返回int值的函数:
function baseToInt($base, $symbols, &$out) {
//get length of the char map, so you can change according to your needs
$radix = strlen($symbols);
//split the chars into an array and initialize variables
$arr = str_split($base,1);
$i = 0;
$out = 0;
//loop through each char assigning values
//chars to the left are the least significant
foreach($arr as $char) {
$pos = strpos($symbols, $char);
$partialSum = $pos * pow($radix, $i);
$out += $partialSum;
$i++;
}
}
这个电话和戈兰的完全一样:
$number = 123456;
$symbols = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$strBase = "";
intToBase($number, $symbols, $strBase);
$intReturn = 0;
baseToInt($strBase, $symbols , $intReturn);
echo $strBase."<br>"; //e7w
echo $intReturn; //123456
Goran的答案是完全有效的,但多年来PHP变得更加严格,并略微改变了引用的使用,因此要将其更新到今天,我们可以使用:
function intToBase(int $num)
{
$symbols = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// get the radix that we are working with
$radix = strlen($symbols);
$out = [];
if ($num === 0) {
// if our number is zero then we can just use the first character of our symbols and we are done.
return $symbols[0];
}
// otherwise we have to loop through and rebase the integer one character at a time.
while ($num > 0) {
// split off one digit
$r = $num % $radix;
// convert it and add it to the char array
array_unshift($out, $symbols[$r]);
// subtract what we have added to the compressed string
$num = (int)floor(($num - $r) / $radix);
}
return implode('', $out);
}
此版本将适用于严格类型。
基于上述算法,我使用GMP修复了它,使其也能处理非常长的数字。它的代码更有效,并且共享两种编码/解码方式:
function intToBase(int|string $num)
{
// sometimes $num is sent using gmt_intval which of type string on very very large numbers
if ( ! is_numeric($num) ) return 0;
$symbols = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// get the radix that we are working with
$radix = strlen($symbols);
$out = [];
if ($num === 0) {
// if our number is zero then we can just use the first character of our symbols and we are done.
return $symbols[0];
}
// otherwise we have to loop through and rebase the integer one character at a time.
while ($num > 0) {
// split off one digit
$r = (int) gmp_div_r ($num, $radix); // $num % $radix
// convert it and add it to the char array
$out[] = $symbols[$r];
// subtract what we have added to the compressed string
$num = gmp_div ( gmp_sub($num, $r), $radix); // ($num-$r) / $radix
}
return implode('', array_reverse($out));
}
function baseToInt($base) {
$symbols = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
//get length of the char map, so you can change according to your needs
$radix = strlen($symbols);
//split the chars into an array and initialize variables
$arr = str_split($base,1);
$out = 0;
//loop through each char assigning values
//chars to the left are the least significant
foreach($arr as $char) {
$pos = strpos($symbols, $char);
$out = gmp_add ( gmp_mul ($out,$radix), $pos); // ($out*radix) + $pos
}
return $out;
}