PHP中的无符号右移/零填充右移/ >>>(Java/JavaScript等效)

frz*_*bor 6 javascript php java bit-manipulation bit-shift

在将此标记为重复之前,请阅读以下内容,并检查我的代码*我的更新代码!

所以我的问题是,我必须实现Java/JavaScript'>>>'(无符号右移/零填充右移),但我无法以完全相同的方式工作.

我已经选择了我在SO和Web上找到的11个最有希望的实现(链接在代码中添加为注释)并添加了一些测试用例.不幸的是功能返回的Java/JS相同响应所有的测试.(也许其中一些只在32位系统上工作)

实时代码+ JS + PHP结果演示(点击运行):
http://phpfiddle.org/main/code/bcv7-bs2q*
http://phpfiddle.org/main/code/dpkw-rxfe

最接近的功能是:

// http://stackoverflow.com/a/27263298
function shr9($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)); 
}
Run Code Online (Sandbox Code Playgroud)

// http://stackoverflow.com/a/25467712
function shr11($a, $b) { 
    if ($b > 32 || $b < -32) {
        $m = (int)($b/32);
        $b = $b-($m*32);
    }

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

    if ($a < 0) 
    { 
        $a = ($a >> 1); 
        $a &= 2147483647; 
        $a |= 0x40000000; 
        $a = ($a >> ($b - 1)); 
    } else { 
        $a = ($a >> $b); 
    } 
    return $a; 
}
Run Code Online (Sandbox Code Playgroud)

不幸的是shr9失败了(-10 >>> -3)和*(32 >> 32),但是唯一通过(-3 >>> 0); 和shr11失败(-3 >>> 0)和(32 >>> 32).

测试用例:

         0 >>> 3    == 0 
         3 >>> 0    == 3 
         0 >>> -3   == 0 
        -3 >>> 0    == 4294967293 (in JS); -3 (in Java)  
        10 >>> 3    == 1 
        10 >>> -3   == 0 
       -10 >>> 3    == 536870910 
       -10 >>> -3   == 7 
-672461345 >>> 25   == 107 
        32 >>> 32   == 32 
       128 >>> 128  == 128 
Run Code Online (Sandbox Code Playgroud)

编辑:我发现这只是在JavaScript中-3 >>> 0等于(为什么?),但在Java中,它等于.不幸的是,这并没有改变我仍然无法通过所有测试的任何功能的事实.4294967293-3


*大更新:

从PHP 7开始,位移负数被认为是无效的并且导致:" 致命错误:未捕获的算术错误:按负数移位 ".据此,我认为我们不必通过这些测试,所以我已经更新了问题和代码.

frz*_*bor 6

在研究了问题中的两个函数(“shr9”和“shr11”)并合并/调整好的部分后,我终于找到了解决方案。所有测试都通过了(我什至在演示中添加了更多),并且它也适用于负数移位。

[现场演示]

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; 
}
Run Code Online (Sandbox Code Playgroud)

这段代码不仅准确,而且速度也很快。
基准测试结果:100000 次循环:0.25 秒
基准测试:http : //phpfiddle.org/main/code/mj68-1s7e