【C#】ビット演算:特定のNビット目がON(1)かOFF(0)かを判定する方法

目次

ビットフラグの状態判定

C#でビット演算を用いて複数の状態(フラグ)を一つの数値変数で管理する際、「特定のビットをON/OFFする」操作と並んで重要なのが、「特定のビットが現在ON(1)なのか、OFF(0)なのかを判定する」操作です。

例えば、「読み取り許可」フラグ(例: 3ビット目)が立っているかどうかをbool値として取得したい場合などに、このテクニックが使用されます。

この記事では、ビット演算の&(AND)と<<(左シフト)を組み合わせた、特定のビットの状態を判定する標準的な方法を解説します。


準備:2進数表示ヘルパー

ビットの状態を視覚的に確認するため、16ビットの符号なし整数(ushort)を2進数文字列に変換するヘルパーメソッドを用意します。

using System;

public class BitCheckExample
{
    /// <summary>
    /// 16ビット符号なし整数(ushort)を、0埋めした2進数文字列に変換します。
    /// </summary>
    static string ToBinaryString(ushort value)
    {
        // 16桁の2進数文字列(例: "0000_0001_0010_0100")として整形
        string binary = Convert.ToString(value, 2).PadLeft(16, '0');
        return $"{binary.Substring(0, 4)}_{binary.Substring(4, 4)}_{binary.Substring(8, 4)}_{binary.Substring(12, 4)}";
    }

Nビット目の状態を判定するロジック

特定のNビット目がON(1)かどうかを判定するには、以下の3ステップのロジックを使用します。

  1. マスクの作成: 1 << n を使用し、判定したいNビット目(0から数える)だけが1で、他がすべて0の「マスク」を作成します。
  2. & (AND) 演算の適用: 判定したい元の値と、作成したマスクで & (AND) 演算を行います。
  3. 結果の判定:
    • もし元の値のNビット目が0だった場合、0 & 10 になります。マスクの他のビットはすべて0なので、&演算の結果は全体として 0 になります。
    • もし元の値のNビット目が1だった場合、1 & 11 になります。&演算の結果は、マスクと**同じ値(0ではない)**になります。

したがって、&演算の結果が0でなければ(!= 0)、Nビット目はON(1)であったと判定できます。

判定式: (value & (1 << n)) != 0


コード例:ビットの状態判定

0b_0000_0101_0011_0000 という値について、ONになっているビット(例: 8ビット目)と、OFFになっているビット(例: 3ビット目)をそれぞれ判定してみます。

    public static void Main()
    {
        // 判定対象の値 (8ビット目, 9ビット目, 10ビット目がON)
        ushort permissionFlags = 0b_0000_0101_0011_0000; // (Decimal: 1328)
        Console.WriteLine($"判定対象の値: {ToBinaryString(permissionFlags)}");
        Console.WriteLine("---");

        // --- 例1: ONになっているビットの判定 (8ビット目) ---
        int bitPositionOn = 8;
        
        // 1. マスクを作成 (1 << 8) = 0b_0000_0001_0000_0000
        ushort maskOn = (ushort)(1 << bitPositionOn);
        Console.WriteLine($"判定マスク(8): {ToBinaryString(maskOn)}");

        // 2. AND演算
        //   0000_0101_0011_0000 (元の値)
        // & 0000_0001_0000_0000 (マスク)
        // -------------------------
        //   0000_0001_0000_0000 (結果: 0ではない)
        ushort resultOn = (ushort)(permissionFlags & maskOn);
        Console.WriteLine($"AND演算結果: {ToBinaryString(resultOn)}");

        // 3. 結果の判定 (0ではないか?)
        bool isBitOn = (resultOn != 0);
        Console.WriteLine($"第{bitPositionOn}ビットはONか: {isBitOn} (True)");
        Console.WriteLine("---");

        // --- 例2: OFFになっているビットの判定 (3ビット目) ---
        int bitPositionOff = 3;

        // 1. マスクを作成 (1 << 3) = 0b_0000_0000_0000_1000
        ushort maskOff = (ushort)(1 << bitPositionOff);
        Console.WriteLine($"判定マスク(3): {ToBinaryString(maskOff)}");

        // 2. AND演算
        //   0000_0101_0011_0000 (元の値)
        // & 0000_0000_0000_1000 (マスク)
        // -------------------------
        //   0000_0000_0000_0000 (結果: 0である)
        ushort resultOff = (ushort)(permissionFlags & maskOff);
        Console.WriteLine($"AND演算結果: {ToBinaryString(resultOff)}");

        // 3. 結果の判定 (0ではないか?)
        bool isBitOff = (resultOff != 0);
        Console.WriteLine($"第{bitPositionOff}ビットはONか: {isBitOff} (False)");
    }
} // クラスの閉じ括弧

出力結果:

判定対象の値: 0000_0101_0011_0000
---
判定マスク(8): 0000_0001_0000_0000
AND演算結果: 0000_0001_0000_0000
第8ビットはONか: True (True)
---
判定マスク(3): 0000_0000_0000_1000
AND演算結果: 0000_0000_0000_0000
第3ビットはONか: False (False)

まとめ

特定のNビット目がON(1)かどうかを判定するC#の標準的なイディオムは、&(AND)演算子を用いて0と比較することです。

bool isBitOn = (value & (1 << n)) != 0;

この式は、valueのNビット目だけを抽出し、その結果が0ではない(=ビットが立っていた)場合にtrueを返します。これは、ビットフラグの読み取りにおいて非常に高速で効率的な操作です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次