开发者

PHP shift right

开发者 https://www.devze.com 2023-01-08 12:34 出处:网络
i am trying to implement DataOutputStream in php (DataOutputStream from java language) in java code they shif开发者_Go百科t right variables like this >>>

i am trying to implement DataOutputStream in php (DataOutputStream from java language) in java code they shif开发者_Go百科t right variables like this >>>

in php i can only shift like this >>

how can i do this in php ?

thank you


You can implement the behavior of the unsigned right shift operator >>> with the signed shift operators like this:

The value of n>>>s is n right-shifted s bit positions with zero-extension. If n is positive, then the result is the same as that of n>>s; if n is negative, the result is equal to that of the expression (n>>s)+(2<<~s) if the type of the left-hand operand is int, and to the result of the expression (n>>s)+(2L<<~s) if the type of the left-hand operand is long. The added term (2<<~s) or (2L<<~s) cancels out the propagated sign bit.


In masked form for any platform (32bit, 64bit... future as long as PHP_INT_MAX is defined) which would perhaps offer a performance benefit (no branching):

function uintRShift($uint,$shift)
{
    //if ($shift===0) return $uint;
    //PHP_INT_MAX on 32 =7FFFFFFF, or zero & 32 ones
    $mask=PHP_INT_MAX>>($shift-1);
    return $uint>>$shift&$mask;
}

The mask setup puts all zeros for the left-most $shift bits of $uint. Note: Uncomment the first line if you want to be able to/tolerant of zero shifting a negative/large number (since the mask will modify a negative/large number even with $shift=0).

The unit testing code to show it's working in 32 bit:

class UintRShiftTest extends PHPUnit_Framework_TestCase {
   public function provide_shifts() {
      return array(
         /*   start         shift       end*/
          array(0,          4,          0)
         ,array(0xf,        4,          0)
         ,array(0xff,       4,          0xf)
         ,array(0xfffffff,  4,          0xffffff)
         ,array(0xffffffff, 4,          0xfffffff)
         ,array(-1,         4,          0xfffffff)//Same as above
         ,array(0,          1,          0)
         ,array(0xf,        1,          0x7)
         ,array(-1,         1,          0x7fffffff)
         );
   }

   /**
    * @dataProvider provide_shifts
    */
   function test_uintRShift($start,$shift,$end) {
      $this->assertEquals($end,uintRShift($start,$shift));
   }
}

For what it's worth the above mentioned function:

function uintRShift_branch($uint,$shift)
{
   if ($uint<0) {
      return ($uint>>$shift)+(2<<~$shift);
   } else {
      return $uint>>$shift;
   }
}

Fails automated test:

  • #4 Reports -1. This can perhaps be justified by PHP reporting 0xffffffff as a large positive number (documentation suggests large integers are automagically switched to floats, although the bit shift seems to treat it as a regular integer still)

  • #8 Results in -2147483649 which is actually correct (same as 0x7fffffff) but below the minimum int value for PHP:-2147483648

0

精彩评论

暂无评论...
验证码 换一张
取 消