PHP shift right
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
isn
right-shifteds
bit positions with zero-extension. Ifn
is positive, then the result is the same as that ofn>>s
; ifn
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 reporting0xffffffff
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 as0x7fffffff
) but below the minimum int value for PHP:-2147483648
精彩评论