很常见的一道题,网上也有各种各样的解法,备忘一下。
首先来看十进制整数的加法,123 + 999,将其分为三步来运算:
(1)对每一位相加,不考虑进位。当有进位时,舍弃。如下:
123
+ 999
= 012
(2)考虑进位的影响。观察可发现,当个位相加有进位时,实际上少加了10,当百位有进位时,实际上少加了100,依次类推。因此,第二步操作我们得到因为没考虑进位少加的数。当没有进位时为0,当有进位时,舍弃个位,留下十位。比如5 + 6 = 11,舍弃个位,留下十位,为1,即 5 + 6 = 1。对每一位做如此操作:
123
+ 999
= 111
个位: 3 + 9 = 1 少加了10
十位: 2 + 9 = 1 少加了100
百位: 1 + 9 = 1 少加了1000
共少加了 1100,即 111 * 10 = 1110。因为是十进制,所以将进位相加得到的数 111 * 10,即为由于忽略进位少加的数
(3)将第一步和第二步所得到的数相加:
012
+ 1100
= 1112
得到最后的结果。
推广到二进制,逢2进1。举例:15 + 11,转化成二进制就是:1111 + 1011,还是按照上面的三个步骤:
(1)每一位相加,不考虑进位:
1111
+ 1011
= 0100
(2)考虑进位,算出少加的数
1111
+ 1011
= 1011
对应到二进制,从右到左:
第一位进位:少加了2
第二位进位:少加了4
第四位进位:少加了16
因为是二进制,需要将 1011 * 2,对应到二进制中,就是左移一位,变成 10110
(3)将第一步和第二步的数相加:
0100 = 4
10110 = 22
和为: 26
使用二进制加法时:
0100
+ 10110
= 11010
实际上,在上述过程中仍然有进位,继续利用上面的方法。因此,利用二进制实现加法实际上是个循环的过程。
用程序实现上述步骤:
第一步中,1 + 1 = 0, 0 + 0 = 0, 1 + 0 = 1, 0 + 1 = 1 ,实际上符合异或的操作(相同为0,不同为1)
第二步中,1 + 1 = 1, 0 + 0 = 0, 1 + 0 = 0, 0 + 1 = 0, 实际上符合与操作(只有都为1时才为1)
第三步就是对第一步和第二步的重复。
代码如下:
while(cin >> n >> m){ while(m){ int sum = n ^ m; int temp = (n & m)<<1; n = sum; m = temp; } cout << n << endl; }