我在面试时被问到这个问题。我没有回答,实际上我不明白它是如何工作的。
int add(int x, int y)
{
while (y != 0)
{
int carry = x & y;
x = x ^ y;
y = carry << 1;
}
return x;
}
我不是在问为什么会产生正确答案......首先,为什么算法最终会停止?对我而言,这并不是那么明显。
要使其停止,carry
必须成为0
。不能有人解释一下吗?
答案 0 :(得分:6)
line 1 : int carry = x & y;
line 2 : x = x ^ y;
line 3 : y = carry << 1;
如果x = 1; y = 2;
每个数字的二进制:
0 = 00
1 = 01
2 = 10
3 = 11
代码第1行,
&安培; (按位AND) 如果两个操作数
中存在二进制AND运算符,则将其复制到结果中x是1 =&gt; 01
y是2 =&gt; 10
结果进位是=&gt; 00(0)
第2行代码,
^(按位异或) 二进制异或运算符如果在一个操作数中设置,则不会同时复制该位。
x是1 =&gt; 01
y是2 =&gt; 10
结果x是=&gt; 11(3)
第3行代码, 变量进位需要左移1位, 所以现在携带是0 =&gt; 00和向左移位1表示进位现为0.结果y为(0)。而循环停止因为y现在是0。
x的最终结果是3。
希望这会对你有所帮助。
答案 1 :(得分:2)
我们举一个例子:
x=13(1101)
y=9(1001)
Loop 1:
-----------------
y!=0 -> carry=(1101)&(1001)=1001(9) [AND Op]
x=(1101)^(1001)=0100(4) [XOR Op]
y=carry<<1 -> y=(carry)x2=10010(18)
Loop 2:
-----------------
y!=0 -> carry=(0100)&(10010)=00000(0)
x=(0100)^(10010)=10110(22)
y=carry<<1 -> y=0
loop terminated.
因此,x是22.So,x ^ y存储和部分,x&amp; y存储进位部分,然后进位(x&amp; y)被移位以匹配数字x ^ y,并且最终对它们进行异或运算并存入x。 x是结果。
答案 2 :(得分:1)
简而言之,关于使用y(以及&#34;携带/ x&amp; y&#34;它变成)来修改x直到它成为两个整数的总和。例如,
y=1 (....0001), x=anything (either .....0 or .....1)
if x ends with 0, x&y=0
//x^y = x becomes ....001 (thereby adding 1)
//since x&y=0 the loop stops
if x ends with 1, x&y=1
//x^y = x
//since y= x&y<<1, new y=(.....000010)
if x ends with 01, x&y=0
//x^y = x becomes ....010 (thereby adding 1)
//since x&y=0 the loop stops
if x ends with 11, x&y=1
//x^y = .....01
//since y= x&y<<1, new y=(......000100)
if x ends with 011
//stuff happens and x becomes ....100 (thereby adding 1)
//loop stops
if x ends with 111
//...
//if x ends with 111111, x becomes ....1000000 (thereby adding 1)
//if x ends with 1111111, x becomes ....10000000 (thereby adding 1)
//if x ends with 11111111, x becomes ....100000000 (thereby adding 1)
//well you get the idea
相同的逻辑适用于y的所有值,并且与正常加法没有太大的区别,只是现在有2个可能的数字(0和1)而不是通常的10(0到9)。