6

So, when using my method to preform a ( >>> ) unsigned right shift in PHP, the result is incorrect when the numbers involve negatives.

PHP Application Results:

INPUT: 10 >>> 3
INPUT: -10 >>> 3
OUTPUT: 1
OUTPUT: 2684354558

JAVA APPLICATION RESULTS:

INPUT: 10 >>> 3
INPUT: -10 >>> 3
OUTPUT: 1
OUTPUT: 536870910

(The top results are correct and generated by Java and then the bottom results are incorrect and generated by PHP)

It's only when the number is negative in PHP that it fails.

The shifts being used in those applications is:

Please help if you can!

Method for shifting in PHP:

function urshift($x, $n){
$mask = 0x40000000;
if ($x < 0){
    $x &= 0x7FFFFFFF;
    $mask = $mask >> ($n-1);
    $ret = ($x >> $n) | $mask;
    $ret = str_pad(decbin($ret), 32, '0', STR_PAD_LEFT);
    $ret[0] = '1';
    $ret = bindec($ret);
} else {
        $ret = (int)$x >> (int)$n;
}
return $ret;
Mitchell M
  • 475
  • 1
  • 7
  • 15

2 Answers2

13

This uRShift is shorter, works correctly with 32- and 64-bit PHP and gives the same result as the Java version on 32-bit PHP which has same size ints as Java;

function uRShift($a, $b)
{
    if($b == 0) return $a;
    return ($a >> $b) & ~(1<<(8*PHP_INT_SIZE-1)>>($b-1));
}

> uRShift(-10,3)  
536870910

> uRShift(10,3)
1
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • Shifting the following example is not working: -672461345 >>> 25 According to JS it should be 107, however it returns 549755813867 . I've searched for your code and found it in a couple of open source projects, and I'm about to use it, so it would be good, to clear things up. See more: http://stackoverflow.com/questions/24659911/unsigned-right-shift-function-not-working-for-negative-input – frzsombor Nov 27 '16 at 19:30
  • ATTENTION! If you are looking for a PHP function that gives the same output as JavaScript, I finally found a working solution! More details, live demo, tests, examples: http://stackoverflow.com/a/43359819/2953830 – frzsombor Apr 19 '17 at 20:16
3

try this function instead.

function uRShift($a, $b) 
{ 
    $z = hexdec(80000000); 
    if ($z & $a) 
    { 
        $a = ($a >> 1); 
        $a &= (~$z); 
        $a |= 0x40000000; 
        $a = ($a >> ($b - 1)); 
    } else { 
        $a = ($a >> $b); 
    } 
    return $a; 
}  
WhyteWolf
  • 456
  • 2
  • 9