位运算与加减乘除

210 阅读1分钟

加法

以9+3为例

十进制

1. 不考虑进位,9+3=2(记为sum)
2. 计算进位,9+3=10(记为carry)
对sum和carry持续上两步,直到carry=0 ,sum 即为所求

即:
loop1:(9+3)
sum=2
carry=10
carry!=0

loop2:(sum+carry)
sum=12
carry=0
carry=0

return sum(12)

化成二进制:9(1001);3(0011)

loop1:
sum=1010
carry=0010
carry!=0

loop2:1010+0010
sum=1000
carry=0100
carry!=0

loop3:(1000+0100)
sum=1100
carry==0
return sum(1100=>12)

不难看出,

sum的结果就是异或(num1 ^ num2)结果,

carry就是与运算后左移位1(num1 & num2 << 1)

所以得到位运算加法:

function Add(num1, num2) {
  while (num2) {
    var t = num1 ^ num2; //不进位的相加
    num2 = (num1 & num2) << 1; //同1则进位
    num1 = t;
  }
  return num1;
}

console.log(Add(19, 13));

减法

在十进制中,3-6可以看做 3+(-6),在位运算中也是如此,我们将加法写成减法来运算,二进制中用补码(取反再加一)来表示负数。

所以减法的实现是:补码器 + 加法器

function Add(num1, num2) {
  while (num2) {
    var t = num1 ^ num2; //不进位的相加
    num2 = (num1 & num2) << 1; //同1则进位
    num1 = t;
  }
  return num1;
}

function substract(num1, num2) {
  let substr = Add(~num2, 1); // 取反再加一
  return Add(num1, substr);
}

本文参考