Tenho um UInt64 armazenado em uma string. Para fins de argumentação, vamos usar o valor máximo, 18446744073709551615. Como o PHP não suporta UInt64, não posso converter isso em um número, caso contrário, bits serão perdidos.
Então minha abordagem inicial foi fazer as malas:
$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
Então isso não está totalmente certo. Internamente, ele ainda foi convertido para um Int64.
Posso compactar com N para obter metade do valor, mas não consigo descobrir como obter a outra metade:
$number = "18446744073709551615";
$packed = pack('N', $number);
$value1 = ??;
$value2 = unpack('N', $packed)[1];
Pedir repetições com N* ou NN não ajuda. Meu cérebro quer deslocar o valor para a direita, mas, novamente, não consigo converter para um inteiro, então nada de operações bit a bit.
Sinto que estou esquecendo algo muito simples. Como obtenho a outra UInt32?
Do meu ponto de vista, você não está deixando passar nada óbvio. O problema é que o PHP não consegue lidar com
UInt64
valores nativamente. Então, em vez de tentar usarpack('J', $number)
(o que ainda requer que o PHP converta a string para um int de 64 bits internamente), eu abordaria assim: usarBCMath
para dividir o número em duasUInt32
partes e compactá-las separadamente. Isso evita qualquer perda de precisão e funciona exclusivamente com strings. Veja como eu faria:Para reverter a operação e retornar a string original: