【问题标题】:Unsigned right shift function not working for negative input无符号右移功能不适用于负输入
【发布时间】:2014-08-30 20:19:14
【问题描述】:

我正在寻找一种在 64 位版本的 PHP 5.5.14 中使用 JavaScript 中的 >>> 函数的方法。我在谷歌搜索中找到了this function

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

这个函数似乎对正数工作正常,但在传递负数时我得到不同的结果。

例如:

PHP:

In: echo uRShift(-672461345, 25);
Out: -149

JavaScript (Chrome 35):

In: -672461345 >>> 25
Out: 107

编辑:

我还尝试了上面链接的答案中提到的其他功能。

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

PHP:

In: echo uRShift(-672461345, 25);
Out: 549755813867

Runnable

【问题讨论】:

标签: javascript php bit-manipulation


【解决方案1】:

常量0x80000000(在此示例中被编写为对hexdec 的调用并存储在$z 变量中)表示最小有符号二进制补码负整数(100000.... 二进制)。表达式~$z 应该给出这个的按位非,即最高的有符号正整数(最终是2147483647)。

原始数字(0x80000000,即2147483648)不能存储为有符号 32位整数,所以通常会存储作为某种浮子。不幸的是,PHP 5.5 认为 ~(2147483648) 等于 -2147483649,如果我们正在处理例如64 位整数.

确实,在 runnable 中回显 PHP_INT_SIZE 表明整数是 8 个字节,即 64 位。因此,算法在 PHP 5.5 中无法正确运行。

要解决这个问题,只需将~$z 替换为静态常量,如下所示:

function uRShift($a, $b) 
{ 
    if ($a < 0) 
    { 
        $a = ($a >> 1); 
        $a &= 2147483647; 
        $a |= 0x40000000; 
        $a = ($a >> ($b - 1)); 
    } else { 
        $a = ($a >> $b); 
    } 
    return $a; 
}

这个功能还有一些弱点;例如,移位 0 就不能正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    相关资源
    最近更新 更多