Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #12611

Re: signed int64 pack/unpack

From Jerry Stuckle <jstucklex@attglobal.net>
Newsgroups comp.lang.php
Subject Re: signed int64 pack/unpack
Date 2014-01-12 11:11 -0500
Organization A noiseless patient Spider
Message-ID <lauer1$mff$1@dont-email.me> (permalink)
References <13b7b4d5-1ae0-4e04-910b-112f9a1631cc@googlegroups.com> <0.27f2c8a43d10a3f72059.20140112024221GMT.87fvot3oqa.fsf@bsb.me.uk> <94a0c833-7c16-4afc-aab4-37e660229187@googlegroups.com> <6b352c09-6253-41c3-a879-44643778d66f@googlegroups.com>

Show all headers | View raw


On 1/12/2014 10:25 AM, cameron7@gmail.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@attglobal.net
==================

Back to comp.lang.php | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

signed int64 pack/unpack cameron7@gmail.com - 2014-01-11 18:18 -0800
  Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-11 21:35 -0500
    Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-11 18:46 -0800
      Re: signed int64 pack/unpack The Natural Philosopher <tnp@invalid.invalid> - 2014-01-12 02:59 +0000
        Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-11 22:03 -0500
        Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-11 19:10 -0800
      Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-11 22:04 -0500
  Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 02:42 +0000
    Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-11 22:01 -0500
      Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-11 19:08 -0800
      Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 03:11 +0000
        Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-11 22:15 -0500
          Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 12:37 +0000
            Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-12 10:51 -0500
              Re: signed int64 pack/unpack Christoph Michael Becker <cmbecker69@arcor.de> - 2014-01-12 17:00 +0100
                Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-12 16:09 -0500
                Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 22:35 +0000
                Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-12 17:59 -0500
                Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-13 01:59 +0000
              Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 22:30 +0000
    Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-11 21:54 -0800
      Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-12 07:25 -0800
        Re: signed int64 pack/unpack Jerry Stuckle <jstucklex@attglobal.net> - 2014-01-12 11:11 -0500
        Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-12 23:27 +0000
          Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-12 16:03 -0800
          Re: signed int64 pack/unpack cameron7@gmail.com - 2014-01-12 16:22 -0800
            Re: signed int64 pack/unpack Ben Bacarisse <ben.usenet@bsb.me.uk> - 2014-01-13 01:20 +0000
  Re: signed int64 pack/unpack Christoph Michael Becker <cmbecker69@arcor.de> - 2014-01-12 17:37 +0100

csiph-web