如何将6 + 31个数字字符塞入22个字母数字字符?

时间:2011-03-24 18:35:29

标签: php compression biginteger

我有一个6位数字和一个31位数字(例如“234536”和“201103231043330478311223582826”),我需要使用PHP在API中填入相同的22个字符的字母数字字段。我尝试将每个转换为基数32(必须使用自定义函数,因为base_convert()不能很好地处理大数字)并加入单字符分隔符,但这只能让我减少到26个字符。它是一个REST API,因此字符需要是URI安全的。

如果可能的话,我真的很想这样做而不创建一个数据库表交叉引用这两个数字与另一个参考值。有什么建议吗?

2 个答案:

答案 0 :(得分:3)

使用62的基数代替。这将为前者提供3.35个字符,为后者提供17.3个字符,总共22个字符。

>>> math.log(10**6)/math.log(62)
3.3474826039165504
>>> math.log(10**31)/math.log(62)
17.295326786902177

答案 1 :(得分:1)

您可以使用bc编写类似pack()的大数字。这是我的快速解决方案,它将您的第二个数字转换为13个字符的字符串。太好了!

<?php
$i2 = "201103231043330478311223582826";

function pack_large($i) {
    $ret = '';
    while(bccomp($i, 0) !== 0) {
        $mod = bcmod($i, 256);
        $i = bcsub($i, $mod);
        $ret .= chr($mod);
        $i = bcdiv($i, 256);
    }

    return $ret;
}

function unpack_large($s) {
    $ret = '0';

    $len = strlen($s);
    for($i = $len - 1; $i >= 0; --$i) {
        $add = ord($s[$i]);
        $ret = bcmul($ret, 256);
        $ret = bcadd($ret, $add);
    }

    return $ret;
}

var_dump($i2);
var_dump($pack = pack_large($i2));
var_dump(unpack_large($pack));

示例输出:

string(30) "201103231043330478311223582826"
string(13) "jàÙl¹9±̉"
string(47) "201103231043330478311223582826.0000000000000000"

由于您需要对URL友好的字符,因此在打包字符串上使用base64_encode,这将为您提供一个20个字符的字符串(如果删除填充,则为18个字符串)。