ビット演算のテクニック
ビット演算でフラグの検査・変更、1 の個数、二の冪を調べられます。短い式でも各変化には理由があります。このレッスンは八ビット全体を表示して検証します。
権限や機能フラグのようにビット自体が意味を持つ時に使います。疎な集合は 1 を一つずつ訪ねられ、popcount(a ^ b) はハミング距離です。容量やアラインメントが二の冪を要求するなら、先にその条件を確認できます。
マスクは穴の開いた型紙です。AND は選択・保持、OR は 1 への設定、反転マスクとの AND は消去です。x - 1 は借りによって末尾を変えます。
最下位の 1 を消す
対象がビット k なら mask = 1 << k を作ります。k だけ 1 です。x & mask で検査、x | mask で設定、x & ~mask で消去します。
OR による設定は冪等で、元が 1 なら変わりません。消去は元に関係なく 0 にします。したがって設定後の消去が元に戻るのは、対象が元々 0 の場合だけです。
x & (x - 1) は最下位のセットビットを消します。正整数から一を引くと、上位は不変、最下位の 1 は 0、その下の 0 は借りで 1 になります。元の x と AND を取れば上位を保ち、新しい下位の 1 は元の 0 で消え、最低の 1 だけがなくなります。0 までの反復数がセットビット数です。
正の二の冪は 1 が一つなので、判定は x > 0 and (x & (x - 1)) == 0。0 も後半の等式を満たすため、x > 0 が必要です。
操作をステップで追う
既定は x = 40 = 00101000、k = 2、mask = 00000100。
40 & 4 = 0なので、ビット 2 は元々 0。- 設定すると
00101000 | 00000100 = 00101100、44。同じマスクで再検査すると非零。 - 可視八ビットの反転マスクは
11111011。00101100 & 11111011 = 00101000。元のビットが 0 だったので、この例は 40 に戻る。 - 元の 40 から数え直す。
40 - 1 = 39 = 00100111、40 & 39 = 32 = 00100000。最低の 1 が消え、カウント 1。 32 - 1 = 31 = 00011111、32 & 31 = 0。カウント 2。二つの 1 に二反復。- 二の冪判定では最初の結果を再利用する。
40 & 39 = 32が非零なので 40 は違う。32 & 31 = 0で 32 は正だから合格。 - 0 は
0 & -1 = 0を満たすが、0 > 0が偽なので完全な判定は拒否する。
32 は受理、40 は複数の 1、0 は正でないことを理由に拒否します。
時間・空間計算量
固定幅の機械語なら、マスク作成、検査、設定、消去、二の冪判定は時間・追加空間とも O(1) です。
Kernighan のカウントは 1 ごとに一反復。セットビット数 p なら O(p) 時間、O(1) 空間です。W ビットでは p <= W なので最悪 O(W)。全位置走査は 1 が一つでも W 位置を調べます。
疎なフラグや各セット位置を処理する時に最低 1 の消去が役立ちます。単純な個数なら言語や CPU のネイティブ popcount も使えます。a ^ b の個数を取ればハミング距離です。
境界ケース
x = 0:カウントは零反復、二の冪判定は false。x = 1:一つの 1 を一回で消し、二の冪と分かる。x = 255 = 11111111:八反復で、このレッスンの最大密度。k = 0、k = 7:最低位と左端の可視ビット。同じマスク式を使う。- 対象がすでに 1:OR は変えないが、その後の消去は元のビットを失う。復元ではない。
よくある間違い
x > 0を省く。0 & -1が 0 なので、0 を誤って二の冪とします。- XOR を消去に使う。
x ^ maskは 0 と 1 の交換です。必ず 0 にするならx & ~mask。 x & (x - 1)だけ暗記する。 借りが最低 1 と下位の接尾部をどう変え、AND がなぜ一つだけ消すかを確認します。- 位置とマスクを混ぜる。
k = 2は位置、1 << k = 4が選択用のマスクです。
簡略化の範囲
入力は非負の 0–255、表示は下位八ビットです。Python は任意精度整数、JavaScript のビット演算は符号付き 32 ビットへ変換します。この範囲なら両コードの結果が一致します。範囲外の符号付きマスク、オーバーフロー、言語別のシフト動作は扱いません。
続けて学ぶ
同じ手法につながるレッスンや、次の概念への入口です。
鍵マークのあるレッスンの操作には有料アクセスが必要です。解説はすべて無料で読めます。
誤りや気になる点を見つけましたか? フィードバックを送る。