无符号右移/零填充右移/& gt;& gt;在PHP中(等效于Java/JavaScript) [英] Unsigned Right Shift / Zero-fill Right Shift / >>> in PHP (Java/JavaScript equivalent)

查看:88
本文介绍了无符号右移/零填充右移/& gt;& gt;在PHP中(等效于Java/JavaScript)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Before flagging this as a duplicate, please read below, and check my code * my updated code!

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

So my problem is that, I have to implement Java/JavaScript '>>>' (Unsigned Right Shift / Zero-fill Right Shift), but I can't get it work exactly the same way.

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

I've selected the 11 most promising implementations I've found on SO and on the web (links are added as comments in the code) and added a few test cases. Unfortunately NONE of the functions returned the same response as Java/JS to ALL of the tests. (Maybe some of them are only working on 32bit systems)

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

Live Code + JS+PHP results demo (click Run):
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)); 
}

// 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; 
}

不幸的是shr9在(-10 >>> -3)和 *(32 >> 32)上失败,但是唯一要通过(-3 >>> 0);并且shr11在(-3 >>> 0)和(32 >>> 32)上也失败.

Unfortunately shr9 fails on (-10 >>> -3) and * (32 >> 32), but is the only to pass (-3 >>> 0); and shr11 fails on (-3 >>> 0) and also (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 

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

I found that -3 >>> 0 is equals 4294967293 only in JavaScript (why?), but in Java, it equals -3. Unfortunately, this doesn't change the fact that I still can't get any function to pass all tests.

*大更新:

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

Since PHP 7, bit shift by a negative number is considered to be invalid and causes: "Fatal error: Uncaught ArithmeticError: Bit shift by negative number". According to this, I think we don't have to pass those tests, so I've updated the question and the codes.

推荐答案

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

After looking into the two functions from the question ("shr9" and "shr11") and merging/tweaking the good parts, I finally found the solution. All tests passed (I even added more in the demo), and it also works for shifts by a negative number.

[实时演示]

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; 
}

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

这篇关于无符号右移/零填充右移/&amp; gt;&amp; gt;在PHP中(等效于Java/JavaScript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆