我将尝试用一个简单的3位示例来解释它(您可以跳过这个示例,直接查看粗体字标记的实际解释,该解释从现在开始我们将介绍如何从发布的代码中实现相同的流程开始)。
假设我们想要将x=0b011和y=0b101相加。首先,我们将最低有效位相加:1+1 = 0b10
carry: x10
x: 011
+
y: 101
-----
xx0
然后我们加上第二位(按照书上的说法,我们需要加上前一阶段的进位,但我们也可以在以后的阶段跳过它):1+0 = 0b1
carry: 010
x: 011
+
y: 101
-----
x10
对第三位执行相同的操作:
0+1 = 0b1
carry: 010
x: 011
+
y: 101
-----
110
现在我们有
carry = 0b010
和一些部分结果
0b110
。
还记得我之前的评论吗?我们会在稍后处理进位。现在就是这个“稍后”的阶段了。现在我们将进位加到我们得到的部分结果上(请注意,如果我们在早期阶段分别为每个位添加进位,则结果相同)。最低有效位的加法:
NEW carry: x00
carry: 010
+
part. res.: 110
-----
xx0
二进制加法:
NEW carry: 100
carry: 010
+
part. res.: 110
-----
x00
第三位加法:
NEW carry: 100
carry: 010
+
part. res.: 110
-----
new part. res. 100
现在 carry = NEW carry, part. res. = new part. res.
,我们再次进行相同的迭代。
对于最低有效位(LSB)
NEW carry: x00
carry: 100
+
part. res.: 100
-----
xx0
对于第二个比特:
NEW carry: 000
carry: 100
+
part. res.: 100
-----
x00
第三位:
NEW carry: 1000 --> 000 since we are working with 3 bits only
carry: 100
+
part. res.: 100
-----
000
现在NEW carry
为0,所以我们已经完成了计算。最终结果是0b000(溢出)。
我确定我没有发现任何东西。现在让我们看看如何从发布的代码中实现相同的流程:
partial result
是没有carry
的结果,这意味着当x
和y
在同一位置具有不同的位时,这些位的总和将为1。如果相同的位是相同的,则结果将为0(1+1 => 0,carry
1和0+0 => 0,carry
0)。
因此,partial result是x ^ y
(请参见XOR操作的属性)。在发布的代码中,它是x = x ^ y;
。
现在让我们来看一下进位(carry)。只有当两个二进制位都是1时,我们才会从单个二进制位加法中得到进位。因此,在以下表达式中,将设置进位位为1的位被标记为1:
x & y
(仅在相同位置上设置的位将保持为1)。但是,进位应该添加到下一个(更高位)二进制位!
carry = (x & y) << 1; // in the posted code it is y = carry << 1
迭代会一直执行,直到carry
为0(就像我们的例子一样)。
y
非零,继续添加(部分)y
似乎是合乎逻辑的:如果为零,则完成,因为对于所有x
,x + 0 == x
。 - unwind