その他
    ホーム 技術発信 DoRuby ビット演算でフラグを管理する
    ビット演算でフラグを管理する
     

    ビット演算でフラグを管理する

    警告: 整合性のない脚注開始用の簡単コード:

    この警告が見当違いであれば、管理画面の 全般設定 > 脚注の開始・終了用の簡単コード > 簡単コードの整合性を検査 にある構文検査の機能を無効にしてください。

    整合性のない脚注開始用の簡単コード:

    “article & 1000) > 0) puts '画像1はtrueです' else puts '画像1はfalseです' end if”

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    業務上、フラグを用いて制御が必要な場面があると思いますが
    1つのテーブルに複数フラグ管理が必要でDBに○○フラグ、▢▢フラグ、△△フラグと
    複数のフラグのカラムが追加が必要なケースがあると思いますが、
    今回は上記の様な複数フラグのカラムを一つのビット演算で管理するケースになります。

    ビット演算とは


    ビット演算とは2進数で表された数値(ビットパターン)を操作する演算のことです。 主にAND、OR、NOTという演算から成り立ちます。

    & (AND)


    AND演算は2つのビットパターンを取り、1つのビットパターンを返す演算子です。 各ビットにおいて双方が1の場合は1を、それ以外の場合は0を返します。

    1 & 1 = 1
    0 & 1 = 0
    1 & 1 = 1
    0 & 0 = 0
    

    | (OR)


    OR演算も2つのビットパターンを取り、1つのビットパターンを返す演算子です。 各ビットにおいてどちらかが1の場合は1を、どちらも0の場合は0を返します。

    1 | 1 = 1
    0 | 1 = 1
    1 | 0 = 1
    0 | 0 = 0
    

    ~ (NOT)


    NOT演算は1つのビットパターンを取り、1つのビットパターンを返す演算子です。 各ビットにおいて1の場合は0を、0の場合は1を返します。

    ~1 = 0
    ~0 = 1
    

    ビット演算を使ったフラグ管理


    数値をビットパターンで表すと、各桁が 0 か 1 で表されます。 したがって 0 を OFF、1 を ON と定義すると大量の状態(フラグ)を一つの数字として 管理することができます。

    例えば記事を管理する画面があり1つの記事に対して画像を4つ設定出来る場合

    article_image1 = false
    article_image2 = false
    article_image3 = false
    article_image4 = false
    

    この例では設定可能画像が4つだけなので何とかなりますが、数が増えると面倒です。
    そんな時はビットパターンを使って状態を管理することを考えます。 以下のようなイメージです。

                image1  image2   image3  image4
    article =   0       0        0       0
    

    フラグを立てる

    # 状態を初期化
    article = 0000
    # 画像1を設定
    article = article | 1000
    # 画像3を設定(画像2は未設定)
    article = article | 0010
    

    フラグを下げる

    # 状態を初期化(画像1,3設定)
    article = 1010
    # 画像1を削除
    article = article & (~1000)
    # 画像3を削除
    article = article & (~0010)
    

    フラグを判定する

    # 状態を初期化(画像1,3設定)
    article = 1010
    
    if ((article & 1000) > 0) 
      puts '画像1はtrueです'
    else
      puts '画像1はfalseです'
    end
    
    if ((article & 0100) > 0) 
      puts '画像2はtrueです'
    else
      puts '画像2はfalseです'
    end
    
    if ((article & 0010) > 0) 
      puts '画像3はtrueです'
    else
      puts '画像3はfalseです'
    end
    
    if ((article & 0001) > 0) 
      puts '画像4はtrueです'
    else
      puts '画像4はfalseです'
    end
    

    出力結果

    画像1はtrueです
    画像2はfalseです
    画像3はtrueです
    画像4はfalseです
    

    仕組み

    2進数のどの桁が1になっているかを見て、flagがtrueかfalseかを判定します。
    元となるフラグの2進数と、現在のステータスの2進数を「&」演算子でビット演算を行うことで、両方が1の時だけtrueになります。

    まとめ

    このようにビット演算を使うことで簡単に大量のフラグを管理することができます。
    フラグを増やしたい時は、定数を増やすだけで判定できるので、管理が簡単になります。