将非常大的数字编码成字符串
Encoding very large numbers into Strings
我一直在尝试使用 PHP 将非常大的整数编码为大写字母序列。将 0 到 25 的值分配给 A~Z 我将 10 亿缩短为 DGEHTYM。如果实现了一个可行的算法,使用不同的大小写、数字甚至符号,结果字符串可能会短得多。然而,我的目标只是大写字母的字符串,也许也带有数字字符以使其更短但不是必须的。
使用笔、纸和我的 phone 的计算器进行编码:
- 找到小于 10 亿的 26 的最高次方(php 有函数
log
)。 10 亿是 6。所以 26^6 = 308,915,776.
- 1,000,000,000 by 308,915,776 是 3.237 有很多小数
- 3 是 D。我们收到了第一封信!
- 现在我们将一遍又一遍地做同样的事情,直到我们得到一个整数:取走整个部分并将剩下的小数乘以 26。我们取出的每一个整体都是一封信。对于 10 亿,我循环了 6 次,直到得到 12,即 M.
也许有更聪明的方法来完成这个,但我还没想出来。
也许我应该换个方式做,但由于缺乏更好的方法,我尝试在 PHP 中复制我的计算,但我遇到了问题:1: 编码以 A (0) 结尾的数字非常困难,例如 1326 就是 BZA 和 2:我无法让 PHP 检测数字是否有小数。我不得不一直将它转换成一个字符串并寻找一个点。
解码字符串更容易。从从右到左,你将每个字母的值乘以 26 的位置次方,除了第一个,它们相加:
D => 3 x (26^6) = 926,747,328
G => 6 x (26^5) = 71,288,256
E => 4 x (26^4) = 1,827,904
H => 3 x (26^3) = 123,032
T => 19 x (26^2) = 12,844
Y => 24 x 26 = 624
M => 12
926,747,328 + 71,288,256 + 1,827,904 + 123,032 + 12,844 + 624 + 12 = 1,000,000,000
有一个类似的问题here,但回答的人似乎不明白 OP 试图完成什么。
您正在从基数 10 转换为 26,这在 base_convert or gmp_strval can handle. They'll give digits in the form of 0-9 and a-p, so you just need to translate those into what you're after with strtr.
等内置函数的范围内
$translate = array_combine(
array_merge(range(0, 9), range('a', 'p')),
range('A', 'Z')
);
echo strtr(base_convert(1000000000, 10, 26), $translate), "\n";
echo strtr(base_convert(1326, 10, 26), $translate), "\n";
//Or if you're working with really big numbers (beyond PHP_INT_MAX):
echo strtr(gmp_strval(1000000000, 26), $translate), "\n";
echo strtr(gmp_strval(1326, 26), $translate);
输出:
DGEHTYM
BZA
DGEHTYM
BZA
或者手动完成,这将使 add/remove 符号更容易用于不同的基础和编码。基本上,您将输入的数字除以底数,使用余数查找该位置的适当符号,然后重复除法结果。
function base10_to_whatevs($num, array $digits)
{
$result = '';
$base = count($digits);
while ($num > 0) {
$remainder = $num % $base;
$num = ($num - $remainder) / $base;
$result = $digits[$remainder] . $result;
}
return $result;
}
$letters = range('A', 'Z');
echo base10_to_whatevs(1000000000, $letters), "\n";
echo base10_to_whatevs(1326, $letters);
DGEHTYM
BZA
我一直在尝试使用 PHP 将非常大的整数编码为大写字母序列。将 0 到 25 的值分配给 A~Z 我将 10 亿缩短为 DGEHTYM。如果实现了一个可行的算法,使用不同的大小写、数字甚至符号,结果字符串可能会短得多。然而,我的目标只是大写字母的字符串,也许也带有数字字符以使其更短但不是必须的。
使用笔、纸和我的 phone 的计算器进行编码:
- 找到小于 10 亿的 26 的最高次方(php 有函数
log
)。 10 亿是 6。所以 26^6 = 308,915,776. - 1,000,000,000 by 308,915,776 是 3.237 有很多小数
- 3 是 D。我们收到了第一封信!
- 现在我们将一遍又一遍地做同样的事情,直到我们得到一个整数:取走整个部分并将剩下的小数乘以 26。我们取出的每一个整体都是一封信。对于 10 亿,我循环了 6 次,直到得到 12,即 M.
也许有更聪明的方法来完成这个,但我还没想出来。
也许我应该换个方式做,但由于缺乏更好的方法,我尝试在 PHP 中复制我的计算,但我遇到了问题:1: 编码以 A (0) 结尾的数字非常困难,例如 1326 就是 BZA 和 2:我无法让 PHP 检测数字是否有小数。我不得不一直将它转换成一个字符串并寻找一个点。
解码字符串更容易。从从右到左,你将每个字母的值乘以 26 的位置次方,除了第一个,它们相加:
D => 3 x (26^6) = 926,747,328
G => 6 x (26^5) = 71,288,256
E => 4 x (26^4) = 1,827,904
H => 3 x (26^3) = 123,032
T => 19 x (26^2) = 12,844
Y => 24 x 26 = 624
M => 12
926,747,328 + 71,288,256 + 1,827,904 + 123,032 + 12,844 + 624 + 12 = 1,000,000,000
有一个类似的问题here,但回答的人似乎不明白 OP 试图完成什么。
您正在从基数 10 转换为 26,这在 base_convert or gmp_strval can handle. They'll give digits in the form of 0-9 and a-p, so you just need to translate those into what you're after with strtr.
等内置函数的范围内$translate = array_combine(
array_merge(range(0, 9), range('a', 'p')),
range('A', 'Z')
);
echo strtr(base_convert(1000000000, 10, 26), $translate), "\n";
echo strtr(base_convert(1326, 10, 26), $translate), "\n";
//Or if you're working with really big numbers (beyond PHP_INT_MAX):
echo strtr(gmp_strval(1000000000, 26), $translate), "\n";
echo strtr(gmp_strval(1326, 26), $translate);
输出:
DGEHTYM
BZA
DGEHTYM
BZA
或者手动完成,这将使 add/remove 符号更容易用于不同的基础和编码。基本上,您将输入的数字除以底数,使用余数查找该位置的适当符号,然后重复除法结果。
function base10_to_whatevs($num, array $digits)
{
$result = '';
$base = count($digits);
while ($num > 0) {
$remainder = $num % $base;
$num = ($num - $remainder) / $base;
$result = $digits[$remainder] . $result;
}
return $result;
}
$letters = range('A', 'Z');
echo base10_to_whatevs(1000000000, $letters), "\n";
echo base10_to_whatevs(1326, $letters);
DGEHTYM
BZA