コンピューターサイエンス入門:理論編
ビットAND演算でフラグ判定
この回でやること
ANDとマスクで特定のフラグを読み解き、結果が0かどうかで状態を確かめます。
- 読む 約 7 分
- 最後にクイズ 1 問
真偽値を何個も持ち回るのはつらい
通知設定を考えます。メールを送るか、プッシュ通知を出すか、SMSを出すか。オンかオフかを個別に持つと、設定が増えるたびに扱う項目も増えていきます。
2進数の1桁も、オンかオフかを表せます。整数の各ビットを別の設定に対応させれば、複数の設定を1つの整数で持てます。このように状態を表すビットをフラグと呼びます。詰めたあとに必要なのが、「この桁は1か」を取り出す道具です。
AND は、桁ごとに独立して計算する
& は2つの数を桁ごとに比べ、両方が 1 の桁だけ 1 を残します。片方でも 0 なら 0 です。
プレーンテキスト
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1足し算と違って繰り上がりはありません。1101 & 1010 は、左から 1&1、1&0、0&1、1&0 を計算して 1000 になります。各桁を独立して比べています。
見たい桁だけ 1 のマスクを当てる
片方を「見たい桁だけ1、ほかは0」にすると、結果に残るのはその桁の情報だけです。この相手役をマスクと呼びます。
Python
MAIL = 0b001
PUSH = 0b010
SMS = 0b100
settings = 0b101 # メールとSMSだけオン
print(settings & MAIL) # 1
print(settings & PUSH) # 0
print(settings & SMS) # 4Pythonの 0b は、続く数字が2進数だという印です。マスクの値は、その桁の重みです。プッシュ通知は右から2桁目なので2、SMSは3桁目なので4になります。
結果は 0 かどうかで見る
SMSはオンなのに、結果は1ではなく4です。ANDが残すのは、その桁の重みだからです。単一のフラグを見るときは、結果が0ならオフ、0でなければオンと読みます。
== 1 で比べると、いちばん右の桁以外はオンでもオフ扱いになります。大きい値が返ったからといって、通知の回数が多いという意味でもありません。
現場の話 UNIXの権限
chmod 755の7は、読み4、書き2、実行1を足した数です。権限 & 2が0でなければ書き込める、という判定が使われています。
例題で確かめる
ファイルの権限が5です。書き込み権限があるかを読み解きます。5は2進数で 101、書き込みのマスク2は 010 です。
プレーンテキスト
101 & 010 = 000結果は0なので書き込みはできません。読み取りと実行はオンでも、書き込みの桁はオフです。3つの権限をまとめた値の大小だけでは、特定の権限があるかは判断できません。