剑指Offer65—不用加减乘除做加法

剑指Offer65

题意

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

 

解题思路

本题考察对位运算的灵活使用,即使用位运算实现加法。

加法公式

 本位/进位的操作刚好对应二进制操作 异或 与

符号        描述        运算规则        
^异或两位不相同,结果为1
&与        两位都为1,结果为1

         这样我们通过 异或 与 操作就完成了加法计算的 一半 (也叫半加器)。

         因为 异或 与 只计算了一半,它只能计算 一位 ;要计算第二位,就要考虑来自低位的进位!所以一个完整的 加法计算 不只有本位的2个 输入 ,还需要来自低位的 进位。这样就是一个完整的 加法计算 (也叫全加器)。

        一个全加器可以计算一个位的加法,多个全加器组合,把低位的进位输出,作为高位的进位输入。

本位/进位处理(十进制)

22 + 89 = 111

  百 十 个
     2  2
   + 8  9
   ------
     0  1 // 本位
     1  1 // 进位

01 是计算后的本位,直接记录。11 是计算后的进位,需要:做 进位逻辑 后进入下轮计算。

什么是进位逻辑? —> 乘以进制数,也就是 11 * 10

而这里没有下轮计算了,最终得到 111:

       0 1
   + 1 1 0
   --------
     1 1 1

同样的逻辑在 二进制 里应用:

a ^ b // 计算出2个加数的二进制下,每一位的本位
a & b // 计算出2个加数的二进制下,每一位的进位

(unsigned)(a & b) << 1 // 进位,做进位逻辑,也就是 * 2

//c++不支持负值左移,需要强制转换为无符号数。进位不存在 负 的情况,所以 unsigned 是修饰 进位

算法流程:

 (和 s )=(非进位和 n )+(进位 c )。即可将 s = a + b 转化为:s=a+b⇒s=n+c

循环求 n 和 c ,直至进位 c = 0 ;此时 s = n,返回 n 即可。

多想想就明白了,用十进制模拟:比如 12+8,个位的本位是0,进位是1;然后个位的进位要乘10,再和十位相加,然后十位的本位为2,进位为0,循环结束。最终的答案就是各个位数(个位、十位)上的本位组合,即20。

C++实现

class Solution 
{
public:
    int add(int a, int b) 
    {
        //循环求进位,直至进位为0
        while(b!=0) //使用while循环,模拟多个加法器(每一位都有对应一个加法器)
        {
            int tmp = (a^b);    //求本位
            unsigned int carry = (unsigned int)(a&b)<<1;  //计算进位。进位不存在 负 的情况。
            a = tmp;
            b=carry;
        }
        return a;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向便是光v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值