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

参考:《原码,反码,补码 详解》

题目描述

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

解题思路

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

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

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

例子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

代码如下:

public int Add(int num1,int num2) {
   while (num2 != 0) {
       int tmp = num1 ^ num2;
       int carry = (num1 & num2) << 1;
       num1 = tmp;
       num2 = carry;
   }
   return num1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值