FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » Imported messages » comp.lang.php » signed int64 pack/unpack
Show: Today's Messages :: Polls :: Message Navigator
Return to the default flat view Create a new topic Submit Reply
Re: signed int64 pack/unpack [message #184596 is a reply to message #184593] Sun, 12 January 2014 16:11 Go to previous messageGo to previous message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma:
Senior Member
On 1/12/2014 10:25 AM, cameron7(at)gmail(dot)com wrote:
> I guess I'll reply with my own solution. Turns out there are 2 separate issues here.
>
> 1) the "signed" bit needs to be flipped back to 0 before converting to int. This is because it appears the conversion from base 2 to base 10 will always assume the end value is positive.
> 2) Because of this, the rest of the bits need to be flipped.
>

True. base_convert

> So I added 2 arguments to the function, one will tell us if we're supposed to be checking for a "signed bit", and the other will tell us if we need to flip bits.
>
> As you'll see I'm still off by 1 in the end result, but I'm sure that's just in the details.
>

That's because when you use 2's compliment, you need to flip the bits
and add one.

>
> I hope you'll all agree, this is really ugly, but seems to work :)
>
> <?php
>
> $i64 = -8223372036854775807;
>
> echo "PACKING: ".$i64.PHP_EOL;
>
> list(,$binary) = getBinaryString($i64, 64);
>
> list(,$i64a) = unpack('N', pack('N', base_convert(substr($binary, 0, 32), 2, 10)));
> list(,$i64b) = unpack('N', pack('N', base_convert(substr($binary, 32, 32), 2, 10)));
>
> list($flag,$i64c)= getBinaryString($i64a, 32, true, true);
> list(,$i64d) = getBinaryString($i64b, 32, false, true);
>
> $unpack = base_convert($i64c.$i64d,2,10);
> $unpack *= $flag ? -1 : 1;
>
> echo "UNPACKED: ".$unpack.PHP_EOL;
>
> function getBinaryString($packed,$bits,$check_signed = false, $flip = false){
> $a = 0x01;
> $binary = '';
> for($x=0; $x<$bits; $x++){
> $binary .= (int)(bool)($a & $packed);
> $a = $a << 1;
> }
> $signed_flag = false;
> if($check_signed && substr($binary,$bits-1,1) === '1'){
> $signed_flag = true;
> }
> if($flip){
> for($x=0;$x<strlen($binary);$x++){
> $binary[$x] = $binary[$x] === '1' ? '0' : '1';
> }
> }
> if($signed_flag){
> $binary = substr($binary,0,$bits-1).'0';
> }
> return array($signed_flag, strrev($binary));
> }
>

I've seen worse :)

However, you might want to check some other functions. The gmp_xxx
functions will work on longer numbers; so will the BCD functions.
There are some suggestions and links under base_convert() in the online
documentation at http://us1.php.net/manual/en/function.base-convert.php.

Of course, if you're on a shared host and can't get them to install the
libraries for you, you're out of luck.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex(at)attglobal(dot)net
==================
[Message index]
 
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic: how did I wind up with double headers?
Next Topic: Switch question
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Fri Sep 20 09:41:57 GMT 2024

Total time taken to generate the page: 0.04767 seconds