我在网上找到了这个代码。但是,我无法得到以下代码背后的逻辑:
public static int add(int a, int b) {
if (b == 0) return a;
int sum = a ^ b; // add without carrying
System.out.println("sum is : "+sum);
int carry = (a & b) << 1; // carry, but don’t add
return add(sum, carry); // recurse
}
答案 0 :(得分:2)
让我们看一个例子(为简单起见使用8位)
a = 10010110
b = 00111101
a^b
是xor,它为1
在一个数字中有1
而在另一个数字中有0
的地方提供a^b = 10101011
。在我们的例子中:
0 + 0 = 0
自0 + 1 = 1
,1 + 0 = 1
和1
以来,剩下要处理的唯一列是两个数字都有a^b
的列。在我们的示例中,无论
00010100
+ 00010100
都很短
1 + 1 = 10
是。在二进制, 00101000
,所以上述总和的答案是
(a & b) << 1
或a^b
。因此,(a & b) << 1
和a + b
的总和与sum
相同。
因此,假设该过程保证终止,答案将是正确的。但是该过程将终止,因为每次我们递归调用0
时,由于位移<<
,第二个参数在末尾至少还有一个0
。因此,我们保证最终得到完全由if (b == 0) return a;
s组成的第二个参数,以便行{{1}}可以结束该过程并给我们一个答案。
答案 1 :(得分:1)
我们正在添加将整数转换为位并使用按位运算符。
EXOR即^:0 ^ 0和1 ^ 1 = 0,其他情况给出1。
AND即&amp; 1 ^ 1 = 1,..其他情况给出0。
&LT;&LT;或左移。即向左移动并追加0位:0010变为0100
例如。
add(2,3)
2= 0010
3=0011
exor both : to get initial sum : 0001
carry : a &b = 0010
Left shift by 1 bit : 0100 i.e 4
add(1,4)
exor both : 0001 0100 and u get 0101 i.e 5
carry = 0000 <<1 i.e 0000 ..
因为进位为0,它会停止加法并返回前一个和
答案 2 :(得分:1)
例如,考虑5+7
:
5 = 101 (Base 2)
7 = 111 (Base 2)
现在考虑添加两个(基数2)数字:
0+0 = 0 = 0 carry 0
1+0 = 1 = 1 carry 0
0+1 = 1 = 1 carry 0
1+1 = 10 = 0 carry 1
A+B
的总和(不携带)为A^B
且进位为A&B
;当你带一个数字时,它会向左移一位数(因此(A&B)<<1
)。
所以:
5 = 101 (Base 2)
7 = 111 (Base 2)
5^7 = 010 (sum without carrying)
5&7 = 101 (the carry shifted left)
然后我们可以递归来添加进位:
A = 010
B = 1010
A^B = 1000 (sum without carrying)
A&B = 0010 (the carry shifted left)
然后我们可以再次递归,因为我们还有更多要携带的东西:
A' = 1000
B' = 100 (without the leading zeros)
A'^B' = 1100 (sum without carrying)
A'&B' = 0000 (the carry shifted left)
现在没有东西可以携带 - 所以我们可以停下来,答案是1100 (base 2) = 12 (base 10)
。
算法只是实现十进制加法作为(longhand)二进制加法,使用or
来添加,并使用位移and
来查找进位并将递归,直到没有其他东西可以携带(这将始终发生,因为bitshift每次向进位附加另一个零,因此每次递归至少再多一位不会每次都生成进位值。
答案 3 :(得分:0)
这是补充表:
+ 0 1
-- --
0 | 0 1
1 | 1 10
▲
如果忽略进位▲
,您会发现它与XOR表相同:
^ 0 1
-- --
0 | 0 1
1 | 1 0
因此,如果将两个数字与按位XOR组合在一起,则无需进位即可逐位添加。
现在,携带什么?只有在两个输入均为1时才会出现这种情况。
您可以使用AND:
获得& 0 1
-- --
0 | 0 0
1 | 0 1
但是,在将一个位置向左移动之后,需要将其添加到总和中,因为它带有&#34;#34;结束,因此(a & b) << 1
因此,您可以在不携带和携带本身的情况下计算加法。如何在不添加的情况下将它们添加到一起?简单!通过递归这个加法的定义!
请参阅@ pbabcdefp关于递归总是终止的原因的答案。