题目:实现一个Add函数,让两个整数相加,但是不能使用+ - * /等四则运算符。
从题目来看这道题还是比较苛刻了,其实解决起来也不难。既然不能使用四则运算,应该是本能的就想到使用位操作了。首先来讲解一下大致的思路,使用 异或^ 操作来完成对应位相加操作,再使用 按位与& 操作来记录有进位的位,将按位与&的结果左移一位来完成进位。将这两个操作放到一个循环中,直到没有进位为止。接下来看看详细讲解。
(这部分讲的比较啰嗦,如果已经有了一定的理解了可以直接看代码)
分别将两个加数用二进制来表示,那么,这两个加数相对应的比特位可以分为四种情况(1 和 0, 0 和 1,0 和 0,1 和 1),而这四种情况又可以归纳分为两种情况,对应位相同或者相异。相异的话就比较简单了,一个是0,一个是1,它们相加,结果一定是1(在这里不考虑进位),那么,一个简单的异或操作(相异结果为1,相同结果为0)就可以将对应位相异的情况解决了。
再看看对于对应位相同的情况,如果都是0,那么很显然,对应位相加,结果依然为0。但如果是1的话,它们相加就需要向高位进一位,其实就是 1+1 = 1 0(这里为二进制表示),怎么实现呢?使用一个按位与&(都为1的情况结果为1,其他情况结果为0)操作,刚好将此种情形挑选了出来,但是,此时只是标记出了对应位都为1的位,还需将按位与出来的结果左移一位,按位与出来的1就变成1 0(二进制表示)了,注意:结果为0时移多少位结果还是0,并不会有什么影响。
那么,问题来了,如果有进位,势必会对高位产生影响,刚刚异或出来的结果就是不完整的。还需让高位计算出来的结果加上刚进的位,既然又有相加,又要考虑相加的两个比特位的情况了(是 0和1 还是 1和1),其实,这就跟最开始的算法一样了,所以,这就是一个循环,当没有进位的时候,就是循环结束的时候了。
代码
循环实现
int
Add(
int
left
,
int
right
)
{
int
sum = 0;
int
carry = 1;
while
(carry)
{
sum =
left
^
right
;
carry = (
left
&
right
) << 1;
left
= sum;
right
= carry;
}
return
left
;
}
递归实现
int
_Add(
int
left
,
int
right
)
{
if
(
right
== 0)
return
left
;
else
return
_Add(
left
^
right
, (
left
&
right
) << 1);
}
int
main()
{
int
ret = 0;
ret = Add(100, 128);
ret = _Add(52, 36);
return
0;
}