ビットAND演算でフラグ判定
ビットAND演算でフラグ判定
このレッスンで分かること
- 2 進数の世界では、
ANDORXORNOTといった ビット演算 が CPU の最も基本的な命令として用意されています- ビット 1 桁同士の
AND(&) は、両方が1のときだけ結果が1になります- この規則を 複数桁 に拡張するときは、桁ごとに独立して計算します
ビットAND演算でフラグ判定 とは
ビット単位の AND 演算を使って、指定したビットが立っているかを判定する関数を実装する。本レッスンでは、ビットAND演算でフラグ判定 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
2 進数の世界では、AND OR XOR NOT といった ビット演算 が CPU の最も基本的な命令として用意されています。条件分岐や算術演算と比べても飛び抜けて高速で、ライブラリの内部や OS、ゲーム開発、ネットワーク処理など、あらゆるところで使われています。
本レッスンでは、その入り口として ビット単位の AND 演算 を学びます。題材は「ある整数 n の k ビット目が 1 か 0 かを判定する関数」です。
ビット演算は CPU の最速命令の 1 つ。条件分岐より圧倒的に速い。
AND の真理値表
ビット 1 桁同士の AND (&) は、両方が 1 のときだけ結果が 1 になります。それ以外はすべて 0 です。
プレーンテキスト
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1この規則を 複数桁 に拡張するときは、桁ごとに独立して計算します。たとえば 1101 & 1010 は 1000 になります。
桁ごとに独立して AND を取る。これがビット演算の基本中の基本。
特定ビットを取り出す「マスク」
ビット AND の最も典型的な用途は マスク です。たとえば n の最下位ビット (LSB) を取り出したいときは n & 1 と書きます。
n = 13 = 1101のとき、n & 1 = 1101 & 0001 = 0001 = 1n = 12 = 1100のとき、n & 1 = 1100 & 0001 = 0000 = 0
つまり n & 1 の結果は、n が 奇数 なら 1、偶数 なら 0 です。剰余演算 n % 2 と同じ結果ですが、ビット演算の方が高速です。
k ビット目を取り出したいときは、マスクを 1 << k (左に k だけシフト) で作ります。たとえば k = 2 のマスクは 0100 です。n & (1 << k) が 0 でなければ k ビット目が立っていることを意味します。
Mermaid 図
図のポイント (テキスト併記)
- 上の例では
n = 13 = 1101の2ビット目を確認しています
上の例では n = 13 = 1101 の 2 ビット目を確認しています。マスク 0100 との AND を取ると 0100 (非ゼロ) になるため、2 ビット目は立っていると判断できます。
Python での実装
Python
def isBitSet(n, k):
return (n & (1 << k)) != 0たった 1 行です。1 << k でマスクを作り、n との AND が非ゼロかどうかで判定します。返り値は True または False です。
JavaScript での実装
JavaScript
function isBitSet(n, k) {
return (n & (1 << k)) !== 0;
}JavaScript のビット演算は 32 ビット整数として扱われる点に注意が必要です。n が極端に大きい数 (2^31 以上) の場合、思った通りに動かないことがあります。本レッスンではその範囲を超えない値だけ扱います。
フラグ管理への応用
ビット AND のもう 1 つの典型的な使い方が フラグ管理 です。たとえば「読み取り権限 / 書き込み権限 / 実行権限」をビットで管理するとき、READ = 1 (0b001)、WRITE = 2 (0b010)、EXECUTE = 4 (0b100) のようにビットを 1 つずつ割り当て、permissions & WRITE で書き込み権限の有無を判定できます。UNIX のファイルパーミッション (chmod 755) の 7 という数字も、まさにこの仕組みで READ + WRITE + EXECUTE = 4 + 2 + 1 = 7 を表しています。
UNIX の
chmodの数字はビットフラグそのもの。7 = 111は全権限を意味する。
よくある間違い
1 つ目は (n & 1 << k) != 0 のように 括弧を省略 するケース。Python では << の方が & より優先順位が 高い ため、括弧なしでも n & (1 << k) と正しく解釈されます。ただし可読性のために明示的に括弧を付けるのが望ましいスタイルです。2 つ目は n & mask == 0 の記述が混乱を招くケース。C や JavaScript では == が & より優先順位が高いため n & (mask == 0) になりますが、Python では & の方が == より優先順位が高いため (n & mask) == 0 と解釈されます。Python で書く場合は意図通りに動きますが、他言語からの移植時には注意が必要です。3 つ目は k が負 や 整数のビット幅を超える ようなケースで未定義動作になる可能性があることです。
やってみよう
isBitSet(13, 0)isBitSet(13, 1)isBitSet(13, 2)isBitSet(13, 3)を全部試して、1101の各桁を確認する。n & 0xFFを計算すると、nの下位 8 ビットを取り出せる。色情報のRGBのR成分だけを抜き出すときに使われる。n & 0x0Fで下位 4 ビット、n & 0xF0で上位 4 ビット (1 バイト内) を取り出せる。- パーミッション (
READ=1, WRITE=2, EXECUTE=4) を組み合わせた値7からEXECUTEだけ落とすには? 次のレッスンのOR/XORで扱う。
ビット AND は マスク と フラグ判定 の 2 つが基本パターン。覚えるとコードが格段に短く、速くなります。
よくある質問
Q. ビット演算は実務でいつ使いますか?
A. フラグ管理(permission の rwx)、画像処理(マスク)、ハッシュ計算の高速化などで使います。複数の真偽値を 1 つの整数にまとめると、メモリ削減と演算高速化の両方が得られます。例えば 8 個の権限を 1 byte で表せます。
Q. AND / OR / XOR の代表的な使い道は?
A. AND は「特定ビットの確認・抽出」(flags & PERM_READ)、OR は「ビットの立て上げ」(flags |= PERM_WRITE)、XOR は「ビット反転や暗号化」で使います。XOR は 2 回かけると元に戻る性質から、簡易暗号や両端ポインタの入れ替えなどに応用できます。
Q. シフト演算で割り算しても良いですか?
A. 正の整数の 2 のべき乗での除算なら x >> n と x / (1<<n) は同じ結果になります。ただし負の数では言語ごとに挙動が違う(算術シフトと論理シフトの区別)ため、可読性と安全性のために通常の演算子を使い、性能ボトルネックでのみシフトを検討してください。
次のレッスン
次は OR / XOR でフラグを操作する に進みましょう。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- ビットAND の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. ビットAND とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- n と k は 0 以上の整数と仮定して良い (k は 30 未満)
- ビット演算 & と << を使うこと
- 戻り値は boolean (True/False or true/false) で返すこと
入出力例
test-cases.txt
isBitSet(13, 0) → true
isBitSet(13, 1) → false
isBitSet(13, 2) → true
isBitSet(13, 3) → true
isBitSet(13, 4) → false
isBitSet(0, 0) → false
isBitSet(1024, 10) → true