ビットフラグとは何かをフロントエンジニア目線で整理してみた
🎄この記事は bitA Tech Blog Advent Calendar の12日目の記事です。
はじめに
案件で、フラグのステータスによって表示内容を変える実装が必要になりました。ステータスは9種類あり、数値で管理すべきか、文字列で管理すべきかで迷っていたところ、バックエンドエンジニアの夫に相談してみたところ——
夫「ビットフラグがいいと思う」
「ビット…フラグ…?」という状態だったのでビットフラグについて調べてみました。
ビットフラグとは?
ビットフラグは、1つの整数値の中に、複数の ON/OFF 状態をまとめて持たせるための仕組みです。
コンピュータの世界ではすべての情報が最終的に「0」と「1」で表現されます。このビット列の中に、各状態を1ビットずつ割り当てて管理するのがビットフラグです。
┌─┬─┬─┬─┬─┬─┬─┬─┐
│0│1│0│0│1│1│0│0│
└─┴─┴─┴─┴─┴─┴─┴─┘
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
各ビット(ON/OFF)
複数のbooleanを並べる代わりに、1つの数値で複数の状態を管理できる点が特徴です。
例えば
RPGの状態異常をフラグで管理する例を考えてみます。
| ビット番号 | 10 進数 | ステータス |
|---|---|---|
| 0 | 1 | 毒 ☠️ |
| 1 | 2 | 眠り 😴 |
| 2 | 4 | 沈黙 🤐 |
| 3 | 8 | 混乱 😵💫 |
| 4 | 16 | 暗闇 😎 |
これをビット列で表すと次のようになります。
暗 混 黙 眠 毒
┌─┬─┬─┬─┬─┐
│0│0│0│0│0│ ← 0 が OFF、1 が ON
└─┴─┴─┴─┴─┘
4 3 2 1 0 ← ビット番号
例えば、「毒 + 沈黙 + 混乱」が付与されている状態は以下のように表現できます。
暗 混 黙 眠 毒
0 1 1 0 1 ← ON のビット
JavaScriptで確認します。
let state = 0; // 最初は全部 OFF
// 毒を付与
state = state | 1; // ビット論理和演算子(どちらか一方でも1なら1を返す)
// 沈黙を付与
state = state | 4;
// 混乱を付与
state = state | 8;
console.log(state); // → 13 (1 + 4 + 8)
console.log(state.toString(2)); // → 1101(2進数表記)
このように、数値13だけで3つの状態を同時に表現できます。
JavaScriptでの基本的な使い方
ビットフラグでは、主に次の3操作を組み合わせて状態を管理します。
1. フラグを立てる(ONにする)
state |= FLAG;
例えば毒を付与するなら 00000 |= 00001 → 00001となり、対応するビットが1になります。
2. フラグを下げる(OFFにする)
state &= ~FLAG;
&(ビット論理積)と ~(ビット否定)を組み合わせることで、特定のビットのみを0にできます。
例:毒を解除する場合 00001 &= ~00001 → 00000
3. フラグが立っているか確認する
if (state & FLAG) {
// フラグがON
}
状態が立っていれば0以外の値になり、条件がtrueになります。
例
const POISON = 1;
const SLEEP = 2;
const SILENCE = 4;
let state = 0;
// 毒と沈黙を付与
state |= POISON;
state |= SILENCE;
// 毒が付与されている?
console.log(state & POISON); // 1 → true
// 沈黙を解除
state &= ~SILENCE;
console.log(state); // 1(毒だけ)
なぜビットフラグが便利なのか
✔ カラムを増やさずに済む
状態ごとにbooleanフラグを追加していくと、テーブル定義やモデルの管理が複雑になります。ビットフラグなら、1つのカラムで複数の状態を表現できるため、スキーマをシンプルに保てます。
✔ 複数の状態を自然に組み合わせられる
複数の条件を同時に持つ状態でも、1つの整数値で表現できます。
複雑なAND条件の組み合わせもビット演算で直感的に扱えます。
✔ 判定が高速で、実装もシンプル
ビット演算(AND や OR)は非常に高速で、処理の意図も明確になります。
「特定の状態がONかどうか?」の判定も一行で書けます。
ただし向かない場合も
ただし、「常にビットフラグが正解」というわけではありません。
- 状態が少ない
- 将来増える予定がない
- 可読性を最優先したい
といった場合は、booleanを素直に並べた方が理解しやすいこともあります。
まとめ
2進数やビット演算に慣れていなかったこともあり、図を描いてようやく理解できましたが、とても良い学びになりました。
結果として案件ではビットフラグを採用しませんでしたが、ON/OFFの状態を多く扱うケースでは、よりシンプルにまとめられる便利な仕組みだと感じました。
👋 最後まで読んでいただきありがとうございました!
Discussion