在PHP

时间:2016-02-19 21:41:02

标签: php floating-point floating-point-conversion

对于一个项目,我需要从MQTT读取信息。有效载荷充满了需要转换的protobuf信息。

对于某个值,我收到5.6904566139035E-28作为浮点数。使用http://www.exploringbinary.com/floating-point-converter/当我勾选单个和原始的十六进制值时,我可以转换它,然后我收到12345678,我应该拥有的值(我知道发送了什么)。

但现在我需要在PHP中进行转换。我不知道如何做到这一点。经过一番阅读后,我发现它是一个浮点,但如何转换就像在该网站上完成。

有人可以帮我解决这个问题!

非常感谢!

1 个答案:

答案 0 :(得分:1)

使用非常神秘的 pack unpack 函数,可以在一行中完成:

function rawSingleHex($num) {
    return strrev(unpack('h*', pack('f', $num))[1]);
}

这个"打包" 将数字作为其二进制表示,然后"在包含一个元素的数组中解压缩" :十六进制格式的二进制表示。此格式的数字顺序相反,因此函数在最终结果中反转。

通过传递浮点数来调用它:

echo rawSingleHex(5.6904566139035E-28);

输出:

  

12345678

没有 pack / pack

(这是我的原始答案,但是第一个选项可用,这不是建议的继续进行方式)

二进制格式在维基百科的Single-precision floating-point format文章中进行了解释。

这是一个实现上述过程的PHP函数:

function rawSingleHex($num) {
    if ($num == 0) return '00000000';
    // set sign bit, and add another, higher one, which will be stripped later 
    $sign = $num < 0 ? 0x300 : 0x200;
    $significant = abs($num);
    $exponent = floor(log($significant, 2));
    // get 24 most significant binary bits before the comma: 
    $significant = round($significant / pow(2, $exponent-23));
    // exponent has exponent-bias format:
    $exponent += 127;
    // format: 1 sign bit + 8 exponent bits + 23 significant bits,
    //         without left-most "1" of significant
    $bin = substr(decbin($sign + $exponent), 1) . 
           substr(decbin($significant), 1);
    // assert that result has correct number of bits:
    if (strlen($bin) !== 32) {
        return "unexpected error";
    }
    // convert binary representation to hex, with exactly 8 digits
    return str_pad(dechex(bindec($bin)), 8, "0", STR_PAD_LEFT);
}

输出与第一个解决方案相同。