I have a UInt64 stored in a string. For the sake of argument, let's use the max value, 18446744073709551615. Since PHP does not support UInt64, I cannot ever convert this into a number, else bits will be lost.
So it my initial approach was packing:
$number = "18446744073709551615";
$packed = pack('J', $number);
$value1 = unpack('N', substr($packed, 0, 4))[1];
$value2 = unpack('N', substr($packed, 4, 4))[1];
var_dump($packed); // 7fffffffffffffff
So that's not quite right. Internally, it was still converted into an Int64.
I can pack with N to get the half the value, but I cannot figure out how to get the other half:
$number = "18446744073709551615";
$packed = pack('N', $number);
$value1 = ??;
$value2 = unpack('N', $packed)[1];
Asking for repeats with N* or NN doesn't help. My brain wants to shift the value to the right, but again, I can't convert to an integer, so no bitwise operations.
I feel like I'm missing something really simple. How do I get the other UInt32?
You're not missing anything obvious from my point of view. The issue is that PHP can't handle UInt64
values natively. So rather than trying to use pack('J', $number)
(which still requires PHP to convert the string to a 64-bit int internally), I’d approach it like this: use BCMath
to split the number into two UInt32
parts and pack those separately. This avoids any precision loss and works entirely with strings. Here’s how I’d do it:
$number = "18446744073709551615";
// Split into high and low 32-bit parts using BCMath
$high = bcdiv($number, bcpow("2", "32"), 0);
$low = bcmod($number, bcpow("2", "32"));
// Pack as two unsigned 32-bit integers (big endian)
$packed = pack("N", (int)$high) . pack("N", (int)$low);
echo bin2hex($packed); // ffffffffffffffff
To reverse the operation and get back the original string:
$unpacked = unpack("Nhigh/Nlow", $packed);
$reconstructed = bcadd(
bcmul((string)$unpacked['high'], bcpow("2", "32")),
(string)$unpacked['low']
);
echo $reconstructed; // 18446744073709551615
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With