JS 不用加减乘除实现加法运算

这是一道算法题,当然也需要理解位运算才能完成。当不能使用 + - * / 来实现加法时,可以使用位运算来实现。

基本位运算符号

& 与,将两个二进制数按位相与,只有同时为1结果才为1

|  或,将两个二进制数按位相或,只要至少有一个为1则结果为1 

异或,将两个二进制数按位相异或,只有两个位相异结果才为1,两个位同为1或同为0结果为0

<< 有符号左移  <<< 无符号左移

>> 有符号右移  >>> 无符号右移

注:

  • 符号位也是可以参与位运算的,0 代表正数,1 代表负数
  • 负数的二进制 = 对应正数的补码,即正数原码取反 + 1

实现代码

/**
 * @param {number} a
 * @param {number} b
 * @return {number}
 */
var add = function(a, b) {
    if(a == 0) return b
    if(b == 0) return a
    return add((a^b),(a&b) << 1)
};

代码解释

a^b 相当于无进位求和,比如 1^9=8 (1001 ^ 0001 = 1000),这里的第一位(最右位)如果是正常求和,则 1+1 应该进一位到第二位,但它无视掉了进位的结果。

(a&b)<< 1 相当于求每一位的进位数,比如(1&9)<< 1 = 2 ((1001 & 0001)<< 1  = 0010),刚刚好得到的就是 a^b 过程中被无视掉的那些进位(本例只涉及一处进位)。

所以 add((a^b),(a&b) << 1) 就相当于 (a^b) + (a&b) << 1,将 两个数无进位求和结果 + 每一次求和得到的进位 。

上述代码就是在不断重复这个过程,直到进位数为0为止,则得到结果。

此外,注意 << 是有符号左移,下面举个例子方便理解。

比如 1 + (-2)求和。

1 ^ (-2)等价于 0001 ^ 1110 = 1111

1 & (-2)<< 1 等价于 (0001 & 1110) << 1 = 0

所以当第一次运算结果传入add函数时,因为此时b形参已经等于0,所以返回 1111 即 -1 (符号位从哪里开始应该底层有记录)

猜你喜欢

转载自blog.csdn.net/weixin_42207975/article/details/107816773