将字节流转换为数字数据类型

时间:2009-04-07 14:42:41

标签: php floating-point 64-bit integer 32-bit

假设我有一个字节流,其中我知道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

4 个答案:

答案 0 :(得分:6)

只需查看处理此问题的Zend_Crypt_Math_BigInteger_BcmathZend_Crypt_Math_BigInteger_Gmp代码:

使用BCmath(Big-Endian)

这基本上是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(Big-Endian)

相同的algorithem - 只是不同的函数名称。

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);
}

更改algorithem以使用Litte-Endian字节顺序非常简单:只需从end到start读取二进制数据:

使用BCmath(Litte-Endian)

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(Litte-Endian)

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);
}

答案 1 :(得分:2)

晚会迟了两年,但是如果有人还在乎: unpack是内置的方式,你可以打开它作为几个32位整数,或作为双。

答案 2 :(得分:1)

这看起来像是一个彻头彻尾的黑客攻击,但它应该可以胜任,假设你有daemonmoi推荐的BC Math函数:

$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);
}

答案 3 :(得分:0)

我知道这不是问题的答案,但请查看the BC Math functions以处理大数字。