【问题标题】:Using bitwise operators in javascript在 javascript 中使用位运算符
【发布时间】:2013-02-04 19:30:51
【问题描述】:

我正在用 javascript 创建一个位掩码。它适用于第 0 位到第 14 位。当我仅将第 15 位设置为 1 时。它会产生“-2147483648”的整数值,而不是“2147483648”。我可以在这里通过返回硬编码的“2147483648”来做一个特殊情况的破解,但我想知道正确的做法。

示例代码:

function join_bitmap(hex_lower_word, hex_upper_word)
{
    var lower_word = parseInt(hex_lower_word, 16);
    var upper_word = parseInt(hex_upper_word, 16);
    return (0x00000000ffffffff & ((upper_word<<16) | lower_word));
}

当 hex_lower_word 为“0x0”且 hex_upper_word 为“0x8000”而不是 2147483648 时,上述代码返回 -2147483648

【问题讨论】:

标签: javascript


【解决方案1】:

这是因为 Javascript 的位移操作使用带符号的 32 位整数。所以如果你这样做:

0x1 << 31   // sets the 15th bit of the high word

它将符号位设置为1,表示负数。

另一方面,你将得到你想要的结果,而不是移位你乘以 2 的幂:

1 * Math.pow(2, 31)

【讨论】:

    【解决方案2】:

    原因是,你正在设置sign bit...

    2147483648 是 1 后跟 31 个二进制零 ...

    当您进行按位运算时,输出始终是带符号的 32 位数字,这使得第 32 位成为符号位,因此您得到一个负数...

    更新

    (upper_word * Math.pow(2, 16))
    

    将给出肯定的2147483648

    但是,您仍然有 OR 操作,这让我们回到了第一格...

    【讨论】:

      【解决方案3】:

      正如前面的答案所解释的,按位运算符是 32 位有符号的。因此,如果在您设置第 31 位的过程中的任何时候,事情都会大错特错。

      在您的代码中,表达式

      (upper_word<<16) | lower_word)
      

      由于括号而首先被评估,并且由于 upper_word 设置了最高位,因此您现在将得到一个负数 (0x80000000 = -2147483648)

      解决方案是确保您不要将1移到第 31 位 - 因此您必须在移位之前将高位字的第 15 位设置为零:

      mask15 = 0x7fff;
      ((upper_word&mask15)<<16|lower_word)
      

      这将处理“太大的数字变成负数”,但它不会完全解决问题 - 它只会给出错误的答案!要回到正确的答案,您需要在答案中设置第 31 位,如果在 upper_word 中设置了第 15 位:

      bit15 = 0x8000;
      bit31 = 0x80000000;
      answer = answer + (upper_word & bit15)?bit31:0; 
      

      重写后的函数就变成了:

      function join_bitmap(hex_lower_word, hex_upper_word)
          {
              var lower_word = parseInt(hex_lower_word, 16);
              var upper_word = parseInt(hex_upper_word, 16);
              var mask15 = 0x7fff;
              var bit15 = 0x8000;
              var bit31 = 0x80000000;
              return 0xffffffff & (((upper_word&mask15)<<16) | lower_word) + ((upper_word & bit15)?bit31:0);
          }
      

      不只是一个“硬编码的特殊情况”——大约有 20 亿个。这会照顾所有人。

      【讨论】:

      • 出色的解决方案。我很佩服!非常感谢。
      • 感谢夸奖!操作位是我的一个爱好......如果你喜欢这个,你可能想看看this recent answer
      • @FYaqoob - 感谢您发现草率的错误并花时间修复它们!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-14
      • 2013-11-23
      • 1970-01-01
      相关资源
      最近更新 更多