bitwiseAddメソッドの説明:
私はこの質問がしばらく前に尋ねられたことを知っていますが、bitwiseAddメソッドがどのように機能するかについて完全な答えが与えられていないので、ここに1つあります。
bitwiseAddにカプセル化されたロジックを理解するための鍵は、加算演算とxorおよびビット単位演算の関係にあります。この関係は、次の式で定義されます(この式の数値例については、付録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)です。この結果から、両方のビットシーケンスに共通するビットのみが結果にコピーされていることがわかります。これから、2つのビットシーケンスに共通ビットがない場合、それらに「&」を適用した結果は0になることがわかります。 これは、加算とビット単位の関係に重要な結果をもたらします。これはすぐに明らかになります。
ここで問題となるのは、式1.2では「+」演算子が使用されているのに対し、bitwiseAddでは使用されていないことです(「^」、「&」、「<<」のみを使用しています)。では、式1.2の「+」をどういうわけか消えさせるにはどうすればよいでしょうか。回答:「強制的に」and式で0を返すようにします。これを行う方法は、再帰を使用することです。
これを実証するために、方程式1.2を1回繰り返します(このステップは最初は少し難しいかもしれませんが、必要に応じて付録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をさらに2回繰り返します。
x + y = 2 * and[2] + xor[2]
x + y = 2 * and[3] + xor[3]
これで、bitwiseAddにある「 temp」変数の役割が強調表示されます。tempを使用すると、ある再帰レベルから次の再帰レベルに渡すことができます。
また、これらすべての方程式で2が乗算されていることにも注意してください。前述のように、この乗算は、and <<=1ステートメントを使用してbitwiseAddのwhileループの開始時に行われます。and [i]のビットは、前のステージのand [i]のビットとは異なるため、この乗算は次の再帰ステージに影響を及ぼします(また、「&」演算子について前に作成した小さなサイドノートを思い出してください。あなたはおそらくこれが今どこに向かっているのかわかるでしょう)。
式1.4の一般的な形式は次のようになります。
x + y = 2 * and[x] + xor[x] (1.5)
with x the nth recursion
ファイナリー:
では、この再帰ビジネスはいつ正確に終了するのでしょうか。
回答:式1.5のand[x]式の2つのビットシーケンス間の交差が0を返すと終了します。これと同等のbitwiseAddは、whileループ条件がfalseになると発生します。この時点で、式1.5は次のようになります。
x + y = xor[x] (1.6)
そしてそれが、bitwiseAddで最後にxorのみを返す理由を説明しています!
これで完了です。このbitwiseAdd私が言わなければならないかなり賢いコードの断片:)
これがお役に立てば幸いです
付録:
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'