剑指offer-47:不用加减乘除作加法

参考:https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 《原码,反码,补码 详解》html

题目描述

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

解题思路

不能使用加减乘除,个人第一反应就是使用 位运算 和 二进制字符串判断 。二进制字符串从末尾到首位一位位判断,也是能得出结果的,可是代码太长,判断多种状况,太麻烦了。这并非一个聪明的方法,舍弃了。函数

 

另外一种方法是位运算。一个数在计算机中会先转成二进制,正数使用原码,负数使用补码,而后进行加减操做。例如计算机中有两个正整数 a 和 b,a + b 则是 a 的原码加上 b 的原码;a - b = a + (-b),即 a 的原码加上 (-b) 的补码。具体的计算过程,请看第一行的参考连接,讲的很详细。在Java中,负数的二进制也是使用补码表示的,因此,只须要考虑如何完成加法便能解决问题。spa

 

首先看两个例子,二进制是如何进行加法的。从两个例子中能够发现,在没有进位的状况下,两个二进制相加,实际上进行了异或操做。在有进位的状况下,先进行异或,获得的是不包含进位的结果 (A)。而后两个二进制再进行位与,获得只带进位的结果 (B)。而后重复以上两个操做,将 (A) 与左移一位的进位 (B) 异或,获得结果 (C);将 (A) 与左移一位的进位 (B) 位与,获得结果 (D);一直到最后位与的结果为0,即没有进位,终止循环。那么在最后 位与 以前的一步 异或 就是最终的结果。code

例子1: 10 + 5 = 15

    1 0 1 0
+   0 1 0 1
--------------
    1 1 1 1
例子2: 9 + 5 = 14

   1 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 0
+  0 1 0 1 异或  0 1 0 1    位与 0 1 0 1 异或 0 0 0 1 0 (左移一位) 位与 0 0 0 1 0
-------------- --------------- -------------- ----------------- -------------------
   1 1 1 0 (A) 1 1 0 0 (B) 0 0 0 1 (C) 1 1 1 0 (D) 0 0 0 0

 代码以下:htm

1 public int Add(int num1,int num2) {
2     while (num2 != 0) {
3         int tmp = num1 ^ num2;
4         int carry = (num1 & num2) << 1;
5         num1 = tmp;
6         num2 = carry;
7     }
8     return num1;
9 }
相关文章
相关标签/搜索