【问题标题】:Convert IEEE754 to hex in PHP在 PHP 中将 IEEE754 转换为十六进制
【发布时间】:2016-02-19 21:41:01
【问题描述】:

对于一个项目,我需要从 MQTT 中读取信息。 payload 中填充了 protobuf 信息,需要进行转换。

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

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

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

非常感谢!

【问题讨论】:

  • 不要自己阅读protobuf,使用现成的库(例如pecl.php.net/package/protocolbuffers
  • 谢谢,我使用了一种 protobuf 解析器,但这给了我这个“答案”
  • 听起来你需要一个更好的 protobuf 解析器,那么! :p 无论如何,你应该可以使用packunpack

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


【解决方案1】:

使用非常神秘的 packunpack 函数,可以单行完成:

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

这个“打包”数字作为它的二进制表示,然后“解压”它在一个具有一个元素的数组中:十六进制格式的二进制表示。这种格式的数字是倒序的,所以函数会在最终结果中倒序。

通过浮点数调用它:

echo rawSingleHex(5.6904566139035E-28);

输出:

12345678

没有包装/包装

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

二进制格式在维基百科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);
}

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

【讨论】:

  • 请查看更新后的答案。使用打包/解包比我第一次提供的功能更好。它会有更好的性能并且非常紧凑。
猜你喜欢
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 2015-06-25
  • 2013-03-10
  • 2012-07-29
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
相关资源
最近更新 更多