XOR演算子を徹底解説:GF(2)で理解するビット演算と実用応用

XOR演算子とは――概要

XOR(排他的論理和、exclusive OR)は、2つのビットやブール値を比較して「どちらか一方だけが真(1)であるときに真になる」演算です。ビット演算ではビット単位で適用され、ソフトウェアやハードウェアの基礎的な操作として広く使われます。数学的には GF(2)(2元体)における加算(加算は 2 での剰余)と一致し、符号なし整数のビットごとの和(キャリーを無視)として理解できます。

真理値表と基本的な性質

2入力のXORの真理値表は次の通りです。

  • 0 XOR 0 = 0
  • 0 XOR 1 = 1
  • 1 XOR 0 = 1
  • 1 XOR 1 = 0

ここから導かれる主な性質:

  • 可換性:a ^ b = b ^ a
  • 結合性:a ^ (b ^ c) = (a ^ b) ^ c
  • 単位元:a ^ 0 = a
  • 自己逆元性(自己相殺):a ^ a = 0
  • 否定との関係(1 ビット):a ^ 1 = ¬a(ビット幅が固定の場合、すべて1とのXORはビット反転)
  • ブール値に対しては「a XOR b」は「a != b」と同値(真偽が異なれば真)

ビット演算としてのXOR

プログラミング言語では一般に ^ がビット単位の排他的論理和(bitwise XOR)を表します(C/C++/Java/JavaScript/Pythonなどで使用)。整数の各ビット位置に対してXORを行うため、マスクによるビットの切り替え(トグル)、パリティ計算、シンプルなチェックサムなどに使われます。

例:8ビットで 0b10110010 と 0b01011100 の XOR は 0b11101110 です。

ブール論理とプログラミングでの扱いの違い

  • 多くの言語で ^ は整数に対するビット演算子だが、言語によってはブールに対しても論理XORとして振る舞う(JavaやC#では boolean に対する ^ は論理XOR)。
  • JavaScript の ^ は常に数値に変換してからビット演算を行うため、論理的な真偽のみのXORを意図する場合は !== を用いるのが確実。
  • Python では bool が int のサブクラスなので True/False に対して ^ を使えるが、論理XORの用途なら != を使うことが多い。

等式と代数的表現(GF(2)として)

XORは GF(2) 上の加算と同等であり、ビットごとの足し算(繰り上がりなし)として振る舞います。これにより線形代数的な操作(線形独立、基底、ガウスの消去法)をビット列に対して行うことが可能です。

重要な恒等式:

  • a ^ a = 0
  • a ^ 0 = a
  • a ^ b = (a & ~b) | (~a & b)(論理式による表現)
  • AND は XOR に関して分配的:a & (b ^ c) = (a & b) ^ (a & c)

注意:XOR が AND に分配するわけではない(XORはAND上で一般に分配則を満たさない)。反例を挙げると a=1,b=1,c=0 のとき a ^ (b & c) ≠ (a ^ b) & (a ^ c) です。

実用例・アルゴリズムでの活用

  • 重複のある配列で一意な要素を見つける:全要素を XOR していくと、ペアで存在する要素は相殺され、1つだけ現れる値が残る(O(n)、追加メモリ不要)。
  • スワップ演算(テンポラリ変数なし):a = a ^ b; b = a ^ b; a = a ^ b。ただし参照が同じ変数やオーバーフロー・可読性を考慮すると実用上の利用は限定的。
  • パリティ計算・簡易チェックサム:ビットの奇遇数(パリティ)を調べる際に XOR を使う。
  • RAID 5 等のストレージ冗長化:ブロックのパリティ計算に XOR を用いてデータ復元を行う。
  • 暗号(ストリーム暗号・ワンタイムパッド):平文と鍵を XOR して暗号化・復号を行う。完全な一回限りのランダム鍵(one-time pad)の場合は理論上完全な秘匿性を持つが、鍵の再利用や予測可能な鍵では安全ではない。
  • 最大XOR部分集合や区間XORクエリ:プレフィックスXORを使った高速な区間XOR取得や、ビットごとの基底を使う最大化問題(XOR basis)など。

ハードウェア実装

XORは論理ゲートとしても基本的で、2入力XORゲートは上の真理値表に従う回路です。論理式では a ⊕ b = (a & ~b) | (~a & b) と表せ、NAND/AND/ORで実装可能です。組み合わせ回路や加算器(桁ごとの加算における和ビットとして)で多用されます。

注意点・落とし穴

  • 型と意味の混同:^ を使う際はその言語でビット演算か論理演算かを確認すること。JSでは真偽値に対する ^ は意図しない動作を生む。
  • ワード幅の扱い:複数ビットの反転を意味するためには「全ビットが1のマスク」とのXORが必要。固定幅を想定せずにビット反転を行うと符号付表現や無限幅表現(Pythonの ~)で期待と異なる可能性がある。
  • 暗号利用時の注意:単純なXOR暗号(繰り返し鍵のXOR)は容易に破られる。暗号学的には安全な鍵管理とランダム性が必須。

まとめ

XORは簡潔ながら強力な演算で、ビット操作、アルゴリズム、ストレージの冗長化、暗号処理など幅広い分野で使われます。可換・結合・自己相殺といった性質や GF(2) としての線形代数の視点を押さえておくと、実装やアルゴリズム設計で役に立ちます。一方で型やビット幅、暗号用途での鍵管理などの注意点も忘れてはいけません。

参考文献