将大数字转换为字母(然后再返回)

时间:2013-12-23 08:22:21

标签: php regex math cryptography encryption

是否存在将大数字存储为字母的概念?例如,假设我有(相对较小的)数字138201162401719,我想缩小字符数(我知道这对节省磁盘空间没有帮助)到尽可能少的字符数。英文字母中有26个字母(但由于我们需要一个零字母,因此我将它们视为25个字母)。如果我开始将我的大号分成25个或更少的碎片,我得到:

  

13,8,20,11,6,24,0,17,19

如果我然后计算字母表的数字a = 0,b = 1,c = 2,d = 3 ...我可以将其转换为:

  

NIULGYART

所以我从15位长(138201162401719)变为9个字符长(NIULGYART)。这当然可以很容易地转换回原始数字。

所以...我的第一个问题是“这是否有名称”而我的第二个问题是“是否有人拥有将进行转换的PHP代码(两个方向) )?“

我正在寻找合适的术语,以便我可以在谷歌做自己的研究......虽然工作代码示例也很酷。

5 个答案:

答案 0 :(得分:2)

这只有在您考虑在处理为字符串之前存储您的号码时才有可能。因为你不能存储庞大的数字作为整数。你将失去精确度(13820116240171986468445将被存储为1.3820116240172E+22),因此很多数字都会丢失。

如果您正在考虑将数字存储为字符串,那么这将是您的答案:

使用的功能:intvalchrpreg_match_all

<?php

$regex = '/(2[0-5])|(1[0-9])|([0-9])/'; 
$numberString = '138201162401719'; 

preg_match_all($regex, $numberString, $numberArray, PREG_SET_ORDER);

echo($numberString . " -> ");

foreach($numberArray as $value){
    $character = chr (intval($value[0]) + 65);
    echo($character);
}

?>

Demo

结果如下:

138201162401719 - &gt; NIULGYART

答案 1 :(得分:1)

我将如何做到这一点:

  • 将大号存储为字符串并将其拆分为包含每个数字
  • 的数字数组
  • 使用substr()
  • 循环遍历数组提取的2位数块
  • 检查数字是否小于26(在这种情况下,它是一个字母)并将它们添加到数组
  • 使用array_map()chr()一起创建上述数组中的新字符数组
  • 内置生成的数组以获取密码

在代码中:

$str = '138201162401719';
$arr = str_split($str);
$i = 0;  // starting from the left

while ($i < count($arr)) {
    $n = substr($str, $i, 2);
    $firstchar = substr($n, 0, 1);
    if ($n < 26 && $firstchar != 0) {
        $result[] = substr($str, $i, 2); 
        $i += 2;   // advance two characters
    } else {
        $result[] = substr($str, $i, 1);
        $i++;      // advance one character
    }
}    

$output = array_map(function($n) {
    return chr($n+65);
}, $result);

echo implode($output); // => NIULGYART

Demo.

答案 2 :(得分:1)

作为替代方案,您可以转换输入整数以在基数26中表示它,而不是基数10.像(伪代码):

func convertBase26(num)
  if (num < 0) 
    return "-" & convertBase26(-num)  // '&' is concatenate.
  else if (num = 0)
    return "A"
  endif
  output = "";
  while (num > 0)
    output <- ('A' + num MOD 26) & output // Modulus operator.
    num <- num DIV 26  // Integer division.
  endwhile
  return output
endfunc

这使用A = 0,B = 1,直到Z = 25和标准位置符号:26 = BA。显然,基本转换很容易逆转。

答案 3 :(得分:0)

我一直试图在PHP中做同样的事情而没有成功。

假设我使用英文字母的26个字母,从A = 0开始到Z为25:

我发现26的最高功率低于我编码的数字。我把它除以我发现的26的最佳力量。在结果中,我取走了整数,将其转换为字母并将小数乘以26.我一直这样做,直到我得到一个整数。得到零是可以的,因为它是A,但如果它有小数,则必须乘以。

对于 DGEHTYM 的10亿,显然是在6个循环中完成的。虽然我的回答演示了如何进行编码,但我担心这样做对PHP无效,这正是我自己想做的事情。我希望这个算法可以帮助那些人。

答案 4 :(得分:0)

strtr()是完成此任务的绝佳工具!它取代了最长的匹配,因为它遍历了字符串。

代码:(Demo

function toAlpha ($num) {
    return strtr($num, range("A", "Z"));
}

$string = toAlpha("138201162401719");
echo "$string\n";
$string = toAlpha("123456789012345");
echo "$string\n";
$string = toAlpha("101112131415161");
echo "$string\n";
$string = toAlpha("2625242322212019");
echo "$string";

输出:

NIULGYART
MDEFGHIJAMDEF
KLMNOPQB
CGZYXWVUT

只需翻转查找数组即可反转转换:https://3v4l.org/YsFZu

合并:https://3v4l.org/u3NQ5


当然,我必须提到,存在将字母序列转换为数字然后再转换为字母的漏洞。考虑到BB变成11,然后误认为11,当再次转换时,它会变成L

有一些方法可以通过调整查找数组来减轻这种情况,但是根据程序要求,这可能不是必需的/不利的。