Чтение 8-байтового целого числа в PHP (биткойн)
Я пытаюсь прочитать значение транзакции биткойна - https://en.bitcoin.it/wiki/Transaction
В вики говорится, что это 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.
1 answers
В качестве документации для PHP unpack()
примечания к функциям, могут произойти странные вещи, если вы попытаетесь распаковать значение без знака длиной, равной собственному целочисленному размеру PHP (т.е. 32 или 64 бита в зависимости от того, как был скомпилирован ваш PHP):
"Обратите внимание, что PHP внутренне хранит целочисленные значения как подписанные. Если вы распакуете большую длину без знака, и она имеет тот же размер, что и значения, хранящиеся внутри PHP, результатом будет отрицательное число, даже если распаковка без знака была указано".
Возможно, это ошибка PHP: если я попрошу значение без знака, я, черт возьми, ожидаю, что получу значение без знака, даже если оно должно быть внутренне представлено в виде поплавка.
В любом случае, один из способов обойти эту "причуду" - распаковать двоичную строку на меньшие куски, скажем, по 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"