Предпосылки
PHP 5.3.6 32-бит (переход на 64-бит невозможен).
Нужно сравнить 2 значения uint64
(8-байтовые целые числа без знака). Один из них я получаю как строку, а другой как двоичную строку.
Вопрос
Можно ли преобразовать строковое представление uint64
в массив из 8 байт или преобразовать массив из 8 байт в строку с uint64
на 32-битном PHP?
Иллюстрация
Я попробовал функцию base_convert
для сравнения строковых представлений base-2 и получил странные результаты. Я знаю, что массив байтов содержит те же uint64
, что и соответствующая строка. Но я понятия не имею, как убедиться, что они представляют одно и то же число.
Это тестовый код с некоторыми реальными значениями для иллюстрации проблемы:
function byte_to_base2string($byte)
{
$byte = base_convert($byte, 10, 2);
$byte = str_pad($byte, 8, '0', STR_PAD_LEFT);
return $byte;
}
function print_info($base10_string1, $bin_string2)
{
$bin_string1 = null; // TODO: how to obtain it?
$base2_string1 = base_convert($base10_string1, 10, 2);
$base2_string1 = str_pad($base2_string1, 64, '0', STR_PAD_LEFT);
$base2_string2 = array_map('byte_to_base2string', $bin_string2);
$base2_string2 = implode('', $base2_string2);
$base10_string2 = base_convert($base2_string2, 2, 10);
echo sprintf("Wrong base-2 string:\n%s\t%s\n", $base10_string1, $base2_string1);
echo sprintf("base-2 string matches $base10_string1, but base-10 string does not\n%s\t%s\n", $base10_string2, $base2_string2);
echo "\n";
// Can't compare because:
// $base2_string1 != $base2_string2
// $base10_string1 != $base10_string2
// $bin_string1 no idea how to convert
}
$strings = [
'288512493108985552',
'288512958990381002',
'288512564016815754'
];
// obtained via unpack('C*', $binaryStr)
$bytes = [
[4, 1, 0, 149, 121, 5, 254, 208],
[4, 1, 1, 1, 241, 183, 239, 202],
[4, 1, 0, 165, 251, 117, 158, 138]
];
array_map('print_info', $strings, $bytes);
И вывод:
Wrong base-2 string:
288512493108985552 0000010000000001000000001001010101111001000001011111111011000000
base-2 string matches 288512493108985552, but base-10 string does not
288512493108985526 0000010000000001000000001001010101111001000001011111111011010000
Wrong base-2 string:
288512958990381002 0000010000000001000000010000000111110001101101111110111111000000
base-2 string matches 288512958990381002, but base-10 string does not
288512958990381002 0000010000000001000000010000000111110001101101111110111111001010
Wrong base-2 string:
288512564016815754 0000010000000001000000001010010111111011011101011001111010000000
base-2 string matches 288512564016815754, but base-10 string does not
288512564016815764 0000010000000001000000001010010111111011011101011001111010001010
Обновлено
Нашел решение (см. мой ответ ниже), но не уверен, что это лучший способ. Все еще надеюсь найти что-то более ясное и прямое.
bindec()
для двоичных строк. Что это даст?The function can convert numbers that are too large to fit into the platforms integer type, larger values are returned as float in that case.
- person ineersa   schedule 19.08.2016bindec
, согласно документам, преобразует двоичное число в целое число или, если необходимо по причинам размера, с плавающей запятой И, да, это дает что-то вроде2.8851249310899E+17
вместо288512493108985552
, теряя точность (как и сказано в руководстве). - person Евгений Савичев   schedule 19.08.2016