剑指offer(48)不用加减乘除做加法

题目描述

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

 

题目分析

不用加减乘除做加法,我第一时间想到的就是用位运算,毕竟计算机是二进制的,所有的操作都是以位运算为基础。

那么假设我们要求7+5=12,二进制就是111+101=1100,我们发现也就是需要处理二进制进位的问题,可是如何处理二进制进位呢?

如果学过计算机体系结构中的进位器就知道怎么做了,不过没学过也没关系,我们可以一步一步的实验,反正位运算就那几种。

 

先实验下异或:res1=111^101=010,(2)(单纯地相加各位的值,没有算进位。)

再实验下与:res2=111&101=101,(判断是否有同1操作,同1操作需要进位。)

或就不用试了,因为与和或是相对的。

好像没什么头绪呀,都只是在这几位操作。

我们发现要产生进位必不可少的就是要使用移位(这里需要使用左移<<)操作符,否则永远都是那几位在运算。

我们知道同1时才需要进位,也就是我们先需要通过与判断同1,再左移一位来实现进位,(这个进位操作是对于所有位。)。

res2<<1=1010,(10)

 

res3=1010^010=1000,(8)

res4=1010&010=010;(再次判断是否有同1操作需要进位。)

我们好像得到了最高位的最终结果(从右数111的第三位和101的第三位的相加进位),但是好像其他位还可以进位。

(进位相当于冒泡操作,还可以进位代表泡泡还没有全部冒上来)

res4<<1=100,(4)

 

res5=1000^100=1100,(我们最终要的结果。)

res6=1000&100=0(代表没有同1操作了,也就是不用进位了)

res6<<1=0;

细心的读者已经发现了一点就是(5+7=10+2=8+4),也就是我们最终把5+7转化为了8+4,就是如此神奇。

 

代码

function Add(num1, num2) {
  while (num2 !== 0) {
    const tmp1 = num1 ^ num2;
    num2 = (num1 & num2) << 1;
    num1 = tmp1;
  }
  return num1;
}

 

posted @ 2018-04-18 10:02  汕大小吴  阅读(713)  评论(0编辑  收藏  举报