Pythonでビット演算を駆使!XORを使った変数スワップの魔法

プログラミングを学んでいると、「どうやって2つの数値をスワップするの?」という基本的な問いにぶつかることがあります。一般的には一時変数を使ったスワップや、Pythonのシンプルなタプルスワップが思い浮かぶでしょう。

# Pythonでおなじみのタプルスワップ
x, y = y, x

便利ですよね。でも、今回は少しマニアックな方法を紹介します。それが、XORを使ったビット演算によるスワップです。この手法は、アルゴリズムの奥深さを垣間見るだけでなく、コンピュータサイエンスの仕組みに触れるいい機会にもなります。

brids

XORスワップの原理を分解してみる

XOR(排他的論理和)は、ビット演算の中でもシンプルかつパワフルな操作です。XORの性質を理解することが、このスワップを理解する鍵です。

XORの詳細はこちら

XORの3つの基本ルール

AとAをXORすると0になる

A ^ A = 0

同じビットをXORすると消える、というわけです。

Aと0をXORするとAが戻る

A ^ 0 = A

0はXORにおいて中立的な存在です。

A ^ Bは、AとBの情報を含む新しい値を作る

A ^ B = C
  1. CにはAとBの違いが詰まっており、これを使って元の値を再現することができます。

これらの性質を使えば、次の3ステップでスワップが可能です。


XORスワップの手順

2つの数値 xy をスワップする場合:

  1. xx ^ y を代入する
    これで x には xy の両方の情報が含まれる。
  2. yx ^ y を代入する
    更新された x(= x ^ y)と元の y をXORすると、元の x が復元されます。
  3. xx ^ y を代入する
    更新された y と更新された x をXORすると、元の y が復元されます。

Python実装:XORスワップをコードで解説

それでは、この仕組みをPythonで実装してみましょう。ステップごとに詳しく説明するので、安心してください。

def swap_with_xor(a, b):
    print(f"初期状態: a = {a}, b = {b}")
    
    # ステップ1: a に a ^ b を代入
    a = a ^ b
    print(f"ステップ1: a = {a} (a ^ b), b = {b}")
    
    # ステップ2: b に a ^ b を代入 (元の a の値)
    b = a ^ b
    print(f"ステップ2: a = {a}, b = {b} (a ^ b)")
    
    # ステップ3: a に a ^ b を代入 (元の b の値)
    a = a ^ b
    print(f"ステップ3: a = {a}, b = {b}")
    
    return a, b

# 使用例
x, y = 5, 10
x, y = swap_with_xor(x, y)
print(f"最終結果: x = {x}, y = {y}")

結果例

このコードを実行すると、次のような出力が得られます。

初期状態: a = 5, b = 10
ステップ1: a = 15 (a ^ b), b = 10
ステップ2: a = 15, b = 5 (a ^ b)
ステップ3: a = 10, b = 5
最終結果: x = 10, y = 5

XORのビット演算を利用することで、xy を効率的にスワップできました!


タプルスワップと比較してみる

もちろん、「Pythonにはこんな複雑なことしなくてもタプルスワップがあるじゃん」という意見はごもっともです。

x, y = y, x

これは可読性も良く、実際のプロジェクトではこの方法を使うのがベストです。ただし、XORスワップは以下のような場面で役立つかもしれません:

  • 低レベルプログラミング(組み込み系):追加の変数を使いたくない場合。
  • アルゴリズムの勉強:ビット演算を深く理解したいとき。

注意点

  1. 同じ値をスワップしようとするとバグる
    • 例えば、x = 5, y = 5 の場合、x ^ y = 0 になるため、この方法は正しく動作しません。
  2. 整数型に限定される
    • XORはビット演算なので、浮動小数点や文字列型では動作しません。

まとめ

XORを使ったスワップは、コンピュータサイエンスの基本的な仕組みを学ぶのに最適です。この手法が実務で必ずしも必要になるわけではありませんが、アルゴリズムの基礎力を鍛えたい方には一度試してみる価値があります。

Pythonの豊富な機能に慣れ親しんでいる方も、こういった低レベルなテクニックに触れることで、新しい発見があるかもしれませんね!

参考:Qiita

上部へスクロール