Преобразование потока байтов в числовой тип данных

Допустим, у меня есть поток байтов, в котором я знаю расположение 64-битного значения (64-битный одноразовый номер). Порядок байтов — Little-Endian. Поскольку целочисленный тип данных PHP ограничен 32-битным (по крайней мере, в 32-битных операционных системах), как мне преобразовать последовательность байтов в числовое представление PHP (я думаю, будет достаточно числа с плавающей запятой)?

$serverChallenge = substr($bytes, 24, 8);
// $serverChallenge now contains the byte-sequence 
// of which I know that it's a 64-bit value

person Stefan Gehrig    schedule 07.04.2009    source источник
comment
Вот как преобразовать массив байтов в float в PHP.   -  person Syed Azhar Abbas    schedule 27.06.2019


Ответы (4)


Только что посмотрел код для Zend_Crypt_Math_BigInteger_Bcmath и Zend_Crypt_Math_BigInteger_Gmp, который решает эту проблему:

Использование BCmath (с обратным порядком байтов)

По сути, это решение, опубликованное Chad Birch.

public static function bc_binaryToInteger($operand)
{
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = bcadd(bcmul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return $result;
}

Использование GMP (с обратным порядком байтов)

Тот же алгоритм - просто разные имена функций.

public static function gmp_binaryToInteger($operand)
{
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = gmp_add(gmp_mul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return gmp_strval($result);
}

Изменить алгоритм для использования порядка байтов Litte-Endian довольно просто: просто прочитайте двоичные данные от конца к началу:

Использование BCmath (с обратным порядком байтов)

public static function bc_binaryToInteger($operand)
{
    // Just reverse the binray data
    $operand = strrev($operand);
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = bcadd(bcmul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return $result;
}

Использование GMP (буквенный порядок байтов)

public static function gmp_binaryToInteger($operand)
{
    // Just reverse the binray data
    $operand = strrev($operand);
    $result = '0';
    while (strlen($operand)) {
        $ord = ord(substr($operand, 0, 1));
        $result = gmp_add(gmp_mul($result, 256), $ord);
        $operand = substr($operand, 1);
    }
    return gmp_strval($result);
}
person Stefan Gehrig    schedule 08.04.2009

Это похоже на полный взлом, но он должен работать, если у вас есть функции BC Math, рекомендованные daemonmoi:

$result = "0";
for ($i = strlen($serverChallenge) - 1; $i >= 0; $i--)
{
    $result = bcmul($result, 256); // shift result

    $nextByte = (string)(ord($serverChallenge[$i]));
    $result = bcadd($result, $nextByte);
}
person Chad Birch    schedule 07.04.2009
comment
На самом деле это действительно выглядит немного некрасиво, но кажется жизнеспособным решением. - person Stefan Gehrig; 08.04.2009
comment
Убрано голосование за, потому что код использует порядок байтов с обратным порядком байтов. Все еще принимаю ответ, потому что он привел меня к правильному пути. - person Stefan Gehrig; 08.04.2009
comment
Ой, это было глупо с моей стороны, я поменяю его. Рад, что все же помогло. - person Chad Birch; 08.04.2009

На вечеринку опоздали на два года, но если кого-то это все еще волнует: распаковать — это встроенный способ перейти сюда, вы можете распаковать его как пару 32-битных целых чисел или как двойной.

person Anon    schedule 15.05.2011

Я знаю, что это не совсем ответ на вопрос, но ознакомьтесь с BC Math функции для обработки больших чисел.

person user39113    schedule 07.04.2009
comment
На самом деле я знаю расширение BCMath, но эти функции не будут полезны, потому что им нужно целочисленное значение в виде строки, но у меня есть только поток байтов, который должен быть преобразован во что-то, что PHP (или BCMath или GMP) может использовать как число... - person Stefan Gehrig; 07.04.2009