【问题标题】:PHP equivalent javascript >>> shift right with zero fill bitwise operators?PHP 等效 javascript >>> 用零填充位运算符右移?
【发布时间】:2011-02-08 04:19:00
【问题描述】:

我可以知道我该怎么做 PHP >>> 吗?此类运算符在 PHP 中不可用,但在 Javascript 中可用。

我刚刚发现一个函数如下:

function zeroFill($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; 
}

但不幸的是,它并不完美。

例如:-1149025787 >>> 0 Javascript 返回 3145941509 PHP zeroFill() 返回 0

【问题讨论】:

  • 你能描述一下它出了什么问题吗?
  • @incrediment:在近百个结果中只有 1 个不正确:-1149025787 >>> 0 在 javascript 中返回 3145941509 但在上面的 zeroFill() 中,它只返回 0。
  • zeroFill 在 64 位上不起作用,知道为什么吗?

标签: php bit-manipulation bit-shift zerofill


【解决方案1】:
/**
 * The >>> javascript operator in php x86_64
 * Usage: -1149025787 >>> 0 ---> rrr(-1149025787, 0) === 3145941509
 * @param int $v
 * @param int $n
 * @return int
 */
function rrr($v, $n)
{
    return ($v & 0xFFFFFFFF) >> ($n & 0x1F);
}

/**
 * The >> javascript operator in php x86_64
 * @param int $v
 * @param int $n
 * @return int
 */
function rr($v, $n)
{
    return ($v & 0x80000000 ? $v | 0xFFFFFFFF00000000 : $v & 0xFFFFFFFF) >> ($n & 0x1F);
}


/**
 * The << javascript operator in php x86_64
 * @param int $v
 * @param int $n
 * @return int
 */
function ll($v, $n)
{
    return ($t = ($v & 0xFFFFFFFF) << ($n & 0x1F)) & 0x80000000 ? $t | 0xFFFFFFFF00000000 : $t & 0xFFFFFFFF;
}

尽情享受吧。

【讨论】:

  • 下一级的东西??
  • RRR 功能在某些情况下无法按预期工作。
【解决方案2】:

负数的速度是十进制-二进制转换的两倍

function zerofill($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)); 

【讨论】:

    【解决方案3】:

    我对此进行了很多研究,从 StackOverflow 和开源项目中收集了超过 11 个版本,但都没有奏效。但最终,我找到了解决方案。

    更多详情,现场演示、测试和示例查看我的问答:
    Unsigned Right Shift / Zero-fill Right Shift in PHP (Java/JavaScript equivalent)

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

    【讨论】:

    • @king_nak 感谢您的编辑!请问可以分享一下原因吗?只是为了使其更加一致还是与安全性或准确性相关的任何事情?
    • 这只是为了清晰和一致。 2147483647 对我来说很模糊,但是使用 0x7FFFFFFF 很明显,除了 MSB 之外的所有位都已设置
    【解决方案4】:

    我研究了网络,并根据给出的解释提出了我自己的 zerofill 函数。此方法适用于我的程序。

    看看:

    function zeroFill($a,$b) {
        if ($a >= 0) { 
            return bindec(decbin($a>>$b)); //simply right shift for positive number
        }
    
        $bin = decbin($a>>$b);
    
        $bin = substr($bin, $b); // zero fill on the left side
    
        $o = bindec($bin);
        return $o;
    }
    

    【讨论】:

      【解决方案5】:

      对于 32 位 (PHP_INT_SIZE == 4) 和 64 位整数 (PHP_INT_SIZE == 8):

      function SHR
      ($x, $c)
      {
          $x = intval ($x); // Because 13.5 >> 0 returns 13. We follow.
      
          $nmaxBits = PHP_INT_SIZE * 8;
          $c %= $nmaxBits;
      
          if ($c)
              return $x >> $c & ~ (-1 << $nmaxBits - $c);
          else
              return $x;
      }
      

      【讨论】:

      • 不适用于 SHR(-1149025787,0),预期为 3145941509,得到 -1149025787
      【解决方案6】:

      您的函数不起作用,因为当$b == 0 时,表达式

      $a >> -1
      

      将被评估,返回 0。

      假设是32位机器,可以加个特殊情况:

      if ($z & $a) {
        if ($b == 0)
          return $a + 0x100000000;
        else {
          ...
      

      【讨论】:

        【解决方案7】:

        不确定这是否适用于 php,我已经设法让它与 C# 一起使用。

        int a, b, result;
        //Instead of 
        result = a >>> b;
        //I do
        result = (int)((uint)a >> b);
        

        我通过调试使用&gt;&gt;&gt; 的代码将它与我从javascript 转换的代码的C# 版本进行比较发现了这一点。在尝试使用b = 0,并使用科学计算器查看由javascript 生成的&gt;&gt;&gt;&gt;&gt; 的不同十六进制/十进制结果。当a 为负数时,&gt;&gt;&gt; 实际上将 aa 设为无符号。

        不确定这是否适用于所有场景,但就我而言,&gt;&gt;&gt; 用于 md5 散列。能够产生类似的输出,我对结果很满意。

        希望有帮助

        【讨论】:

          【解决方案8】:

          这对我有用

          function RRR($a, $b){
              return (int)((float)$a/pow(2,(int)$b));
          }
          

          【讨论】:

          • 在某些情况下这不起作用
          猜你喜欢
          • 2017-04-29
          • 1970-01-01
          • 2015-10-13
          • 1970-01-01
          • 2015-03-19
          • 2022-07-22
          • 2011-05-08
          • 1970-01-01
          • 2012-12-29
          相关资源
          最近更新 更多