在PHP(Bitcoin)中读取8字节整数 [英] Reading an 8 byte integer in PHP (Bitcoin)

查看:181
本文介绍了在PHP(Bitcoin)中读取8字节整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从比特币交易中读取值- https://en.bitcoin.it/Wiki/交易

维基说这是一个8字节的整数,但是我尝试使用unpack进行的尝试都没有给我正确的值作为十进制.

我已经能够从事务中读取除输出值之外的所有其他内容-鉴于我设法将所有字段解析为具有正确值的所有行,看来我正在读取正确的8个字节.

使用:

$bin = hex2bin('00743ba40b000000');
$value = unpack('lvalue', $bin);
// 'value' => int -1539607552

$bin = hex2bin('d67e690000000000');
$value = unpack('lvalue', $bin);
// 'value' => int 6913750

应该是500和0.0691375.

解决方案

作为PHP unpack() 的文档功能说明,如果尝试解压缩长度等于PHP本机整数大小(即32或64位,具体取决于PHP的编译方式)的无符号值,则可能会发生奇怪的事情:

请注意,PHP在内部存储带符号的整数值.如果解压缩一个大的无符号长整型,并且其大小与PHP内部存储的值相同,那么即使指定了无符号解压缩,结果也将是负数." >

可以说,这是一个PHP错误:如果我要求一个无符号值,我非常希望得到 get 一个无符号值,即使它必须在内部表示为浮点数也是如此.

>

在任何情况下,解决此怪癖"的一种方法是将二进制字符串解压缩成较小的块,例如每个8或16位,然后手动重新组装它们,如下所示:

 $bin = pack( 'H*', '00743ba40b000000' );

$words = array_reverse( unpack( 'v*', $bin ) );
$n = 0;
foreach ( $words as $word ) {
    $n = (1 << 16) * $n + $word;
}

echo "$n\n";  // prints "50000000000"
 

I am trying to read the value from a Bitcoin transaction - https://en.bitcoin.it/wiki/Transaction

The wiki says it is an 8 byte integer, but nothing I have tried with unpack gives me the right value as a decimal.

I've been able to read everything else from the transaction except the values out the output - given the other fields I have managed to parse all line up with the correct values it appears I am reading the correct 8 bytes.

With:

$bin = hex2bin('00743ba40b000000');
$value = unpack('lvalue', $bin);
// 'value' => int -1539607552

and

$bin = hex2bin('d67e690000000000');
$value = unpack('lvalue', $bin);
// 'value' => int 6913750

That should be 500 and 0.0691375.

解决方案

As the documentation for PHP's unpack() function notes, strange things may happen if you try to unpack an unsigned value with length equal to PHP's native integer size (i.e. 32 or 64 bits depending on how your PHP was compiled):

"Note that PHP internally stores integral values as signed. If you unpack a large unsigned long and it is of the same size as PHP internally stored values the result will be a negative number even though unsigned unpacking was specified."

Arguably, this is a PHP bug: if I ask for an unsigned value, I damn well expect to get an unsigned value, even if it has to be internally represented as a float.

In any case, one way to work around this "quirk" is to unpack the binary string in smaller chunks of, say, 8 or 16 bits each, and reassemble them manually, like this:

$bin = pack( 'H*', '00743ba40b000000' );

$words = array_reverse( unpack( 'v*', $bin ) );
$n = 0;
foreach ( $words as $word ) {
    $n = (1 << 16) * $n + $word;
}

echo "$n\n";  // prints "50000000000"

这篇关于在PHP(Bitcoin)中读取8字节整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆