php如何实现无符号右移

回复列表(25|隐藏机器人聊天)
  • @Ta / 2021-08-23 / /

    @幕后导演,嗯,上述代码仅限64位php使用,所以我的sint32原本是这样的:

    function sint32($int) {
        if (PHP_INT_MAX == 0x7fffffff) {
            throw new Exception('32位PHP不支持64位整数');
        }
        return unpack('l', pack("L", $int))[1];
    }
    

    不过后来我发现它在32位里没有副作用,只是个空操作,所以把抛出异常删了。

    但是这个无符号右移函数在32位里确实不能达到预期目的,因为负数在32位里& 0xffffffff后依然是负数,并不会消除它的符号位。

    function shr32($x, $bits) {
        if (PHP_INT_MAX == 0x7fffffff) {
            throw new Exception('32位PHP不支持64位整数');
        }
        return ($x & 0xffffffff) >> $bits;
    }
    
  • @Ta / 2021-08-23 / /

    @幕后导演,我最初给的那个右移函数(网上找的)在32位里应该也是对的。然后我的sint32操作在32位里应该也没有副作用(32位php中的所有整数都是32位有符号整数,所以该函数相当于空操作)。所以用这两个函数应该可以写出32位64位结果一致的代码。

    // 32位无符号右移
    function shr32($x, $bits) {
        $c = 0x7fffffff >> ($bits - 1);
        return $c & ($x >> $bits);
    }
    
    // 转为32位有符号整数
    function sint32($int) {
        return unpack('l', pack("L", $int))[1];
    }
    
  • @Ta / 2021-08-23 / /

    这样之所以可以,是因为负数右移时不是在前面补0,而是在前面补1,所以只要把多余的1去掉,结果就是正确的了。

    // 32位无符号右移
    function shr32($x, $bits) {
        $c = 0x7fffffff >> ($bits - 1);
        return $c & ($x >> $bits);
    }
    

    以下是64位结果,32位也一样,只是前面少了32个1。

    php > var_dump(decbin(-2147483647));
    string(64) "1111111111111111111111111111111110000000000000000000000000000001"
    php > var_dump(decbin(-2147483647 >> 3));
    string(64) "1111111111111111111111111111111111110000000000000000000000000000"
    
  • @Ta / 2021-09-03 / /
    // 无符号右移>>>
    function uright($a, $n) {
        // console.log($a);
        if ($n != 0) {
            $c = 2147483647 >> ($n - 1);
            return $c &($a >> $n);
        } else {
            if (is_string($a)) {
                if (PHP_INT_MAX > 2147483647) {
                    $a = intval($a);
                } else {
                    $a = floatval($a);
                } 
            } 
            if (!is_int($a)) {
                $a = intval($a);
            } 
            if ((0 > $a) || ($a > 4294967295)) {
                $a &= 4294967295;
                if (0 > $a) {
                    $a = sprintf('%u', $a);
                } 
            } 
            return $a;
        } 
    }
    
  • @Ta / 2021-09-03 / /

    @卷心菜,这是整数运算逻辑,在任何编程语言中都可以实现。这些逻辑最常见的用途是数据加密或者数字签名。

  • @Ta / 2021-09-04 / /
    @老虎会游泳,老虎见多识广
添加新回复
回复需要登录