以下のルーチンは、a
との値を交換することが期待されます。b
a = a ^ b
b = b ^ a
a = a ^ b
スワップがどのように、またなぜ機能するのかを分析してみましょう。
そのために、値を交換するのではなく、別々の変数に格納して、何が起こっているのかを正確に確認できるようにしましょう。
a0 = a ^ b
b1 = b ^ a0
a1 = a0 ^ b1
以下の XOR のプロパティを使用して方程式を簡略化します。参照用にXOR Properties@Wikipediaを確認してください
- 可換 (
a ^ b == b ^ a
)
- 連想 (
a ^ (b ^ c) == (a ^ b) ^ c
)
a ^ a == 0
0 ^ a == a
a0 = a ^ b // Equation #1
b1 = b ^ a0
a1 = a0 ^ b1
b1 = b ^ a0 // Equation #2
= b ^ (a ^ b) // Using Equation #1
= b ^ (b ^ a) // Property #1
= (b ^ b) ^ a // Property #2
= 0 ^ a // Property #3
= a // Property #4
a1 = a0 ^ b1
= a0 ^ (b ^ a0) // Using Equation #2
= (a ^ b) ^ (b ^ (a ^ b)) // Using Equation #1
= (b ^ a) ^ (b ^ (b ^ a)) // Using Property #1
= (b ^ a) ^ ((b ^ b) ^ a) // Using Property #2
= (b ^ a) ^ (0 ^ a) // Using Property #3
= (b ^ a) ^ a // Using Property #4
= b ^ (a ^ a) // Using Property #2
= b ^ 0 // Using Property #3
= b // Using Property #4
ご覧のとおり、にb1
は の元の値が含まれ、 の元の値が含まれています。つまり、との値が入れ替わっています。a
a1
b
b
a
要約すると、a^=b;b^=a;a^=b
は単なる慣用表現であり、魔法のようなものは何もありません :)
同じことのわかりやすい英語の説明
XOR は、オペランド ビットが異なる場合にビットを設定し、それ以外の場合はビットをリセットします。
例を使用して、行われる変換を見ていきましょう。そのために、次の数値 (2 進数) が変数に割り当てられているとしましょう。
a = 1 1 0 0
b = 1 0 1 0
ステップ #1 : a = a ^ b
// マスクを作成する
a = 0 1 1 0
b = 1 0 1 0
の新しい値が、 givenの古い値を生成するか、 givena
の古い値を生成するためのマスクであると想像してください。a
b
b
a
ステップ #2 : b = b ^ a
//a
マスクを使用して元の値と元の値を復元するb
a = 0 1 1 0
b = 1 1 0 0
はまだ保存/変更されていないため、マスクを使用して のb
元の値を復元できます。これは、このステップで行ったことです。a
ステップ #3 :a = a ^ b
//b
マスクを使用して元の値と元の値をa
a = 1 0 1 0
b = 1 1 0 0
a
変数の元の値が得られたb
ので、同じマスクを使用して の元の値を復元できますb
。このステップの後はマスクは必要ないため、ここでマスクを上書きできます。