面试题65. 不用加减乘除做加法

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

输入: a = 1, b = 1
输出: 2

提示:a, b 均可能是负数或 0;结果不会溢出 32 位整数
思路:

1. 推导思路:

不让用四则运算,那么只能用位运算,这个大部分人都能想到,但是咋用我想了很久都没想到😂,当时就感觉这个有点像模电里面的全加器,全加器就是利用门电路,也就是位运算实现的,先异或算出值,再加上进位得到结果。那么我们就按照全加器来分析一下加法如何实现:

我们先拿十进制举例:现在有5+17=22,

  • 我们先把5和17的个位,不包含进位的的结果求出为:7+5=2(不包含进位)1+0=1,所以为12;
  • 再得到进位10。
  • 最后相加为:12+10=22。

我们下面分析二进制:5的二进制为101,17为10001。

  • 我们先不管进位,即遵循:0+0=0,1+0=1,0+1=1,1+1=0 来算,那么结果为:10100。
  • 得到进位,我们知道只有1+1时才会发生进位,进位为10。
  • 相加为:10100+10=10110,十进制为22。

通过上面得分析,我们知道相加需要三步:得到无进位的值,进位,相加。那么我们需要用位运算将这三步表示出来,我们列个表格来看一下数值和无进位值,进位的关系:

ab异或运算无进位n与运算进位c,加粗表示
0000000
0111000
1011000
1100110

上表我们可以得到n和c如何用位运算得到:第一步:n=a⊕b,第二步:c=(a&b)<<1
对于c的表示肯定有人存在疑惑,我当时也很迷惑,进位一般是存在低位向高位进位,那么如果在二进制中有:
在这里插入图片描述

第三步:将n和c相加,n和c相加的做法和a+b一样,所以有a=n,b=c,一直循环,当b为0时即没有进位时,那么a就是答案。

2. 负数问题: 负数情况下三步走也是可以的,因为呢,在计算机系统中,数值一律用补码来表示和存储。那么 加法、减法可以统一处理(CPU只有加法器)。因此,以上方法同时适用于正数和负数的加法 。

3. 演示: 我们按照三步走思路来演示一下过程,只有了解过程才可以写出代码:

(1)5+17=22,我们用8位一个字节来表示演算:
在这里插入图片描述
(2)我们再举一个负数的例子:3+(-8)=-5
在这里插入图片描述
4. 代码:
那么我们写出代码就很简单了,按照三步思路即可。注意力扣编译器不支持有符号整型左移,所以要先强转为无符号的,但是visual支持。时间空间复杂度均为O(1)

int add(int a, int b) 
{
	int n,s;
	while(b!=0)
	{
		n=a^b;//无进位值
		s=((unsigned int) (a&b)<<1);//进位
		//visual支持:s=(a&b)<<1;
		//将n和c进行加法
		a=n;
		b=s;
	}
	return a;    
}
int main()
{
	cout<<add(1,1);
}

加油哦!🥘火锅快乐。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值