Как я могу втиснуть 6 + 31 цифровых символов в 22 буквенно-цифровых символов? - PullRequest
3 голосов
/ 24 марта 2011

У меня есть 6-значное число и 31-значное число (например, «234536» и «201103231043330478311223582826»), которые мне нужно втиснуть в то же 22-символьное буквенно-цифровое поле в API с помощью PHP. Я попытался преобразовать каждое в основание 32 (пришлось использовать пользовательскую функцию, так как base_convert() плохо обрабатывает большие числа) и объединить с разделителем из одного символа, но это уменьшило меня до 26 символов. Это API REST, поэтому символы должны быть безопасными для URI.

Мне бы очень хотелось сделать это, не создавая таблицу базы данных с перекрестными ссылками на два числа с другим ссылочным значением, если это возможно. Есть предложения?

Ответы [ 2 ]

3 голосов
/ 24 марта 2011

Используйте вместо 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 голос
/ 24 марта 2011

Вы можете написать что-то вроде pack(), которое работает с большими числами, используя bc. Вот мое быстрое решение, оно преобразует ваше второе число в строку из 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, если вы удалите отступ).

...