PHP equivalent javascript >>> shift right with zero fill bitwise operators?
Asked Answered
F

8

6

May I know how can I do PHP >>> ? Such operators is not available in PHP, but is available in Javascript.

I just managed to discover a function as follow:

function zeroFill($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; 
}

but unfortunately, it doesn't work perfectly.

EG: -1149025787 >>> 0 Javascript returns 3145941509 PHP zeroFill() return 0

Freud answered 15/4, 2010 at 0:52 Comment(4)
can you describe what goes wrong with it?Leverick
I imagine you've seen: php.net/manual/en/language.operators.bitwise.phpCrucifix
@incrediment: Out of nearly hundred result only 1 is incorrect: -1149025787 >>> 0 In javascript returns 3145941509 but in zeroFill() above, it just return 0.Freud
zeroFill doesnt work on 64bits, any idea why?Riverine
F
2

I studied around the webs and come out with my own zerofill function, base on the explanation given. This method works for my program.

Have a look:

function zeroFill($a,$b) {
    if ($a >= 0) { 
        return bindec(decbin($a>>$b)); //simply right shift for positive number
    }

    $bin = decbin($a>>$b);

    $bin = substr($bin, $b); // zero fill on the left side

    $o = bindec($bin);
    return $o;
}
Freud answered 15/4, 2010 at 6:17 Comment(0)
S
11
/**
 * The >>> javascript operator in php x86_64
 * Usage: -1149025787 >>> 0 ---> rrr(-1149025787, 0) === 3145941509
 * @param int $v
 * @param int $n
 * @return int
 */
function rrr($v, $n)
{
    return ($v & 0xFFFFFFFF) >> ($n & 0x1F);
}

/**
 * The >> javascript operator in php x86_64
 * @param int $v
 * @param int $n
 * @return int
 */
function rr($v, $n)
{
    return ($v & 0x80000000 ? $v | 0xFFFFFFFF00000000 : $v & 0xFFFFFFFF) >> ($n & 0x1F);
}


/**
 * The << javascript operator in php x86_64
 * @param int $v
 * @param int $n
 * @return int
 */
function ll($v, $n)
{
    return ($t = ($v & 0xFFFFFFFF) << ($n & 0x1F)) & 0x80000000 ? $t | 0xFFFFFFFF00000000 : $t & 0xFFFFFFFF;
}

Enjoy it.

Schmidt answered 21/6, 2018 at 3:6 Comment(2)
Next level stuff 😳👍Determinate
The RRR function doesn't work in some cases as expected.Determinate
A
5

Twice as fast for negative numbers as using the decimal-binary conversions

function zerofill($a,$b) { 
    if($a>=0) return $a>>$b;
    if($b==0) return (($a>>1)&0x7fffffff)*2+(($a>>$b)&1);
    return ((~$a)>>$b)^(0x7fffffff>>($b-1)); 
Airiness answered 3/12, 2014 at 3:47 Comment(0)
C
3

I've researched a lot on this, collected more than 11 versions from StackOverflow and open-source projects, none of them worked. But finally, I found the solution.

For more details, live demo, tests and examples check my question and answer:
Unsigned Right Shift / Zero-fill Right Shift in PHP (Java/JavaScript equivalent)

function unsignedRightShift($a, $b) {
    if ($b >= 32 || $b < -32) {
        $m = (int)($b/32);
        $b = $b-($m*32);
    }

    if ($b < 0) {
        $b = 32 + $b;
    }

    if ($b == 0) {
        return (($a>>1)&0x7fffffff)*2+(($a>>$b)&1);
    }

    if ($a < 0) 
    { 
        $a = ($a >> 1); 
        $a &= 0x7fffffff; 
        $a |= 0x40000000; 
        $a = ($a >> ($b - 1)); 
    } else { 
        $a = ($a >> $b); 
    }

    return $a; 
}
Compatriot answered 12/4, 2017 at 4:19 Comment(2)
@king_nak Thanks for the edit! Can you please share the reasons of it? Is it just for making it more consistent or anything related to safety or accuracy?Compatriot
It is just for clarity and consistency. 2147483647 is quite obfuscated for me, but with 0x7FFFFFFF it is clear that all bits except the MSB are setJug
F
2

I studied around the webs and come out with my own zerofill function, base on the explanation given. This method works for my program.

Have a look:

function zeroFill($a,$b) {
    if ($a >= 0) { 
        return bindec(decbin($a>>$b)); //simply right shift for positive number
    }

    $bin = decbin($a>>$b);

    $bin = substr($bin, $b); // zero fill on the left side

    $o = bindec($bin);
    return $o;
}
Freud answered 15/4, 2010 at 6:17 Comment(0)
O
2

For both 32-bit (PHP_INT_SIZE == 4) and 64-bit integers (PHP_INT_SIZE == 8):

function SHR
($x, $c)
{
    $x = intval ($x); // Because 13.5 >> 0 returns 13. We follow.

    $nmaxBits = PHP_INT_SIZE * 8;
    $c %= $nmaxBits;

    if ($c)
        return $x >> $c & ~ (-1 << $nmaxBits - $c);
    else
        return $x;
}
Outdoors answered 13/2, 2015 at 23:44 Comment(1)
doesn't work with SHR(-1149025787,0), expected 3145941509, got -1149025787Deborahdeborath
R
1

Your function doesn't work because when $b == 0, the expression

$a >> -1

will be evaluated, which returns 0.

Assuming 32-bit machines, you can add a special case:

if ($z & $a) {
  if ($b == 0)
    return $a + 0x100000000;
  else {
    ...
Ryeland answered 15/4, 2010 at 6:28 Comment(0)
J
1

Not sure if this works for php, I've manage to get it to work with C#.

int a, b, result;
//Instead of 
result = a >>> b;
//I do
result = (int)((uint)a >> b);

I found that out by debugging into the code that uses >>> comparing it with C# version of the code I converted from javascript. While trying out with b = 0, and using a scientific calculator to see the different hex/dec result of >> and >>> produce by javascript. When a is negative, >>> actually makes aa as unsigned.

Not sure if that works for all scenario, but for my case the >>> is for md5 hashing. Being able to produce similar output, I'm quite satisfied with the result.

Hope that helps

Jakie answered 17/1, 2011 at 4:41 Comment(0)
V
0

This works for me

function RRR($a, $b){
    return (int)((float)$a/pow(2,(int)$b));
}
Vu answered 16/8, 2013 at 22:59 Comment(1)
In some cases this doesn't workDeterminate

© 2022 - 2024 — McMap. All rights reserved.