[PHP]ビット演算を使ったフラグ処理(2進数のビット操作)

Pocket

PHP を使った動的なサイトでは、「はい(true)」か「いいえ(false)」で表すことの出来るビットフラグを扱うことは多いと思います。
仮にオプション A~E があり、そのうち A, C, E だけ有効になっている状態を表す時、2進数を使ったほうが簡単な場合が有ります。

bit

<?php
// 定数の設定
class OptionInfo {
	const NONE = 0b0;
	const OPTION_A = 0b00001;
	const OPTION_B = 0b00010;
	const OPTION_C = 0b00100;
	const OPTION_D = 0b01000;
	const OPTION_E = 0b10000;
}

$option = OptionInfo::NONE; // 初期値

// フラグを設定
$option |= OptionInfo::OPTION_A;	// Aを有効にする
$option |= OptionInfo::OPTION_C;	// Cを有効にする
$option |= OptionInfo::OPTION_E;	// Eを有効にする

// 有効になっているフラグを表示
if($option == OptionInfo::NONE) echo 'NONE';
if($option & OptionInfo::OPTION_A) echo 'A';
if($option & OptionInfo::OPTION_B) echo 'B';
if($option & OptionInfo::OPTION_C) echo 'C';
if($option & OptionInfo::OPTION_D) echo 'D';
if($option & OptionInfo::OPTION_E) echo 'E';
出力結果: ACE

オプションの A, C, E が有効の時、各ビットが「EDCBA」の順で並んでいるので2進数表記では「10101」のようになります。
それぞれ A=00001, B=00010, C=00100, D=01000, E=100000 という割り当てをしています。
わかりやすくするために定数としてクラスの形で名前をつけています。数字の頭に「0b」をつけるとその数字は2進数のものとして扱われます。

例ではわかりやすくするために直接2進数を使っていますが、現実的にはビットシフト「<<」「>>」を使うほうが扱いやすいかもしれません。(結果は同じです。)

class OptionInfo {
	const NONE = 0b0;
	const OPTION_A = 0b1;
	const OPTION_B = 0b1 << 1;
	const OPTION_C = 0b1 << 2;
	const OPTION_D = 0b1 << 3;
	const OPTION_E = 0b1 << 4;
}

「0b1」は2進数での「1」です。「0b1 << 3」とすると左に 3 ビットシフトして「1000」(2進数表記)となります。全体に3桁左にずれることになります。(厳密には2を3回かけています)

特定のビットの 有効/無効 を切り替えるには次のようにします。

・指定したフラグをオン

$option |= OptionInfo::OPTION_A;

・指定したフラグをオフ
※右辺の「~」に注意

$option &= ~OptionInfo::OPTION_A;

・指定したフラグを反転(XOR)

$option ^= OptionInfo::OPTION_A;

フラグがオンになっているかを調べる場合次のようにします。

if($option & OptionInfo::OPTION_A)

Similar Posts:




  • コメントを残す

    メールアドレスが公開されることはありません。