无符号右移功能不适用于负输入

时间:2014-07-09 17:14:16

标签: javascript php bit-manipulation

我正在寻找一种在PHP 5.5.14的64位版本中使用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

1 个答案:

答案 0 :(得分:0)

常量0x80000000(它被称为hexdec的调用并存储在此示例中的$z变量中)代表最低签名的两个补码负整数(二进制为100000....)。表达式~$z应该给出按位NOT,即最高符号正整数(最终为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不能正常工作。