bitwiseAdd 方法的解释:
我知道不久前有人问过这个问题,但由于没有给出关于 bitwiseAdd 方法如何在这里工作的完整答案。
理解 bitwiseAdd 中封装的逻辑的关键在于加法运算与异或与位运算的关系。该关系由以下等式定义(有关该等式的数字示例,请参见附录 1):
x + y = 2 * (x&y)+(x^y) (1.1)
或者更简单地说:
x + y = 2 * and + xor (1.2)
with
and = x & y
xor = x ^ y
您可能已经注意到这个等式中有一些熟悉的东西:and和xor变量与在 bitwiseAdd 开头定义的变量相同。还有一个乘以 2,在 bitwiseAdd 中是在 while 循环的开头完成的。但我稍后会回来。
在我们继续之前,让我也快速地对 '&' 位运算符做一个旁注。 该运算符基本上“捕获”了应用它的位序列的交集。例如,9 & 13 = 1001 & 1101 = 1001 (=9)。您可以从此结果中看到,只有两个位序列共有的那些位被复制到结果中。由此得出,当两个位序列没有公共位时,在它们上应用 '&' 的结果会产生0。 这对加法-位关系有重要影响,很快就会清楚
现在我们遇到的问题是方程 1.2 使用了“+”运算符,而 bitwiseAdd 没有(它只使用了“^”、“&”和“<<”)。那么我们如何让等式 1.2 中的“+”以某种方式消失呢?答案:通过“强制” and表达式返回 0。我们这样做的方式是使用递归。
为了证明这一点,我将递归方程 1.2 一次(这一步一开始可能有点挑战性,但如果需要,附录 2 中有详细的逐步结果):
x + y = 2*(2*and & xor) + (2*and ^ xor) (1.3)
或者更简单地说:
x + y = 2 * and[1] + xor[1] (1.4)
with
and[1] = 2*and & xor,
xor[1] = 2*and ^ xor,
[1] meaning 'recursed one time'
这里有一些有趣的事情需要注意。首先,您注意到递归的概念听起来很接近循环的概念,实际上就像在 bitwiseAdd 中发现的那样。当您考虑and[1]和xor[1]是什么时,这种联系变得更加明显:它们与在bitwiseAdd中的 while 循环内定义的and和xor表达式是相同的表达式。我们还注意到出现了一种模式:方程 1.4 看起来与方程 1.2 完全一样!
因此,如果保留递归符号,则进行进一步的递归是轻而易举的事。在这里,我们将方程 1.2 再递归两次:
x + y = 2 * and[2] + xor[2]
x + y = 2 * and[3] + xor[3]
现在应该突出显示 bitwiseAdd 中的“temp”变量的作用:temp允许从一个递归级别传递到下一个递归级别。
我们还注意到所有这些等式中的乘以二。如前所述,此乘法是在 bitwiseAdd 的 while 循环开始时使用and <<= 1语句完成的。这种乘法会对下一个递归阶段产生影响,因为 and[i] 中的位与前一阶段的 and[i] 中的位不同(如果您还记得我之前关于 '&' 运算符的小注释您可能会看到现在的情况)。
方程 1.4 的一般形式现在变为:
x + y = 2 * and[x] + xor[x] (1.5)
with x the nth recursion
最后:
那么这个递归业务到底什么时候结束呢?
答:等式 1.5的and[x]表达式中两个位序列的交集返回0时结束。当 while 循环条件变为 false 时,会发生 bitwiseAdd 中的等效情况。此时等式 1.5 变为:
x + y = xor[x] (1.6)
这就解释了为什么在 bitwiseAdd 中我们只在最后返回xor!
我们完成了!这是一段非常聪明的代码,我必须说:)
我希望这有帮助
附录:
1) 等式 1.1 的数值示例
等式 1.1 说:
x + y = 2(x&y)+(x^y) (1.1)
为了验证这一说法,可以举一个简单的例子,比如把 9 和 13 加在一起。步骤如下所示(按位表示在括号中):
我们有
x = 9 (1001)
y = 13 (1101)
和
x + y = 9 + 13 = 22
x & y = 9 & 13 = 9 (1001 & 1101 = 1001)
x ^ y = 9^13 = 4 (1001 ^ 1101 = 0100)
将其代入方程 1.1,我们发现:
9 + 13 = 2 * 9 + 4 = 22 et voila!
2) 演示第一个递归步骤
演示文稿中的第一个递归方程(方程 1.3)表示
如果
x + y = 2 * and + xor (equation 1.2)
然后
x + y = 2*(2*and & xor) + (2*and ^ xor) (equation 1.3)
为了得到这个结果,我们简单地取了上面方程 1.2 的2* 和 + xor部分,并将方程 1.1 给出的加法/按位操作数关系应用于它。这证明如下:
如果
x + y = 2(x&y) + (x^y) (equation 1.1)
然后
[2(x&y)] + (x^y) = 2 ([2(x&y)] & (x^y)) + ([2(x&y)] ^ (x^y))
(left side of equation 1.1) (after applying the addition/bitwise operands relationship)
用方程 1.2 的and和xor变量的定义来简化这一点,得到方程 1.3 的结果:
[2(x&y)] + (x^y) = 2*(2*and & xor) + (2*and ^ xor)
with
and = x&y
xor = x^y
使用同样的简化可以得到等式 1.4 的结果:
2*(2*and & xor) + (2*and ^ xor) = 2*and[1] + xor[1]
with
and[1] = 2*and & xor
xor[1] = 2*and ^ xor
[1] meaning 'recursed one time'