使用 JS 做算法时,需要注意的位运算溢出问题

虽然 ECMAScript 中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位,而是先把数值转换为 32 位整数,再进行位操作,操作完成后再把结果转换为 64 位。所以,对我们(开发者)而言,就好像只有 32 位整数一样。

JS 中常常会通过有符号右移 1 位,来得到除以 2 的向下取整结果。
注意是有符号右移,而不是无符号右移!
因为有符号右移 1 位,可以对负数进行除以 2,比如 -27 >> 1 的结果是 -14

但在某些特殊情况下,需要进行无符号右移。这个情况就是我们需要对一个大于 2147483647 (也就是 0x7FFF_FFFF)的正数进行除 2 时,需要使用无符号右移

可以通过程序证明:

  for (let i = 0x0FFF_FFFF; i < 0x1_0000_0000; i++) {
      if (i >> 1 !== Math.floor(i / 2)) {
          throw new Error(`${i} 溢出`)
      }
  }
  // 最终会输出 Error: 2147483648 溢出

而如果使用无符号右移,则最大能够支持对
可以通过程序证明:

  for (let i = 0x0FFF_FFFF; i <= 0x1_0000_0000; i++) {
      if (i >>> 1 !== Math.floor(i / 2)) {
          throw new Error(`${i} 溢出`)
      }
  }
// 最终会输出 Error: 4294967296 溢出,
// 也就是  0x1_0000_0000 的时候才溢出。

举例说明

为什么说右移是补符号位呢?我们还是拿 -27 举例。

首先,-27 在计算机中的二进制存储是这样的:

        1111 1111 1111 1111 1111 1111 1110 0101

而当我们对 -27 进行有符号左移时,它的最右侧的 1 会消失,同时最左侧会空出一个位置

    _111 1111 1111 1111 1111 1111 1111 0010   ~1~

那么这个位置需要补什么呢?答案是符号位,由于我们是负数,所以它会补上 1
所以结果就是

    1111 1111 1111 1111 1111 1111 1111 0010

这个数字转换为十进制就是 -14。为什么这个二进制是 -14 呢?当然是我们算出来的:

           1111 1111 1111 1111 1111 1111 1111 0010 (某个数字的补码形式)
        ~  0000 0000 0000 0000 0000 0000 0000 1101 (对其取反)
        ++ 0000 0000 0000 0000 0000 0000 0000 1110 (然后加一,得到 14)
                                                   在前面加个负号
                                                   就得到 -14 了
                                                   所以我们知道这个补码
                                                   的十进制是 -14

既然有符号右移都说了,那再说说无符号右移的。

还是拿 -27 举例,步骤是一样的。

首先,-27 在计算机中的二进制存储是这样的:

    1111 1111 1111 1111 1111 1111 1110 0101

而当我们对 -27 进行有符号左移时,它的最右侧的 1 会消失,同时最左侧会空出一个位置

    _111 1111 1111 1111 1111 1111 1111 0010 ~1~

那么这个位置需要补什么呢?答案是 0,无论是正数还是负数,都会补上 0
所以,结果会是

    0111 1111 1111 1111 1111 1111 1111 0010

而这个数字自己计算一下,就知道是二进制的 2147483634
自己在 js 中运行一下,就可以知道答案

    console.log(-27 >>> 1) // 输出 2147483634

原文链接:https://juejin.cn/post/7355414702434467859 作者:Linhieng

(0)
上一篇 2024年4月9日 下午5:08
下一篇 2024年4月10日 上午10:00

相关推荐

发表回复

登录后才能评论