System.Collections.BitArrayクラスはビット列を操作するためのクラスで、任意長かつ固定長のビット列を扱うことができます。 BitArrayクラスでは、個々のビット(桁)をbool
/Boolean
型として扱います。
BitArrayクラスは、bool型のコレクションの形でビット列を表現するクラスとも言えます。 BitArrayクラスには、ビット単位の操作のほか、AND演算・OR演算などのビット演算を提供するメソッドが用意されています。
BitArrayクラスは非ジェネリックインターフェスのみを持つコレクションクラスですが、扱う型がbool型に限定されているため、foreachによる列挙(IEnumerableインターフェイス)以外の操作はタイプセーフとなっているコレクションクラスです。
BitArray
BitArrayクラスは可変長のコレクションではなく、固定長のコレクションとして動作します。 つまり、固定長の桁数のビット列を扱います。 他のコレクションとは異なり、Addなどのメソッドによって要素(=ビット列の桁)を追加・削除したりコレクションのサイズ(=ビット列の桁数)を変更したりすることはできません。
BitArrayクラスでは、ビット列となるbyte型、int型、bool型のいずれかの配列をコンストラクタに指定してインスタンスを作成します。 int型・byte型の配列では、配列内の各要素の各ビットがBitArrayインスタンスに設定されます。 bool型配列では、各要素が1ビットを表すものとしてBitArrayインスタンスに設定されます。 このほかに、ビット列の桁数を指定してインスタンスを作成することもできます。
BitArrayクラスをforeach文で列挙すると、ビットの各桁がbool型の値(0=False
、1=True
)として列挙されます。 下位の桁から列挙されるため、ビット順としてはリトルエンディアンとなります。 Countプロパティを参照すれば、BitArrayの現在の要素数(=桁数)を取得することができます。
ビットの取得・設定
BitArrayクラスでは、他のコレクションと同様にインデクサによってインデックス(=桁)を指定してビット値を取得・設定することができます。
インデックスを指定した取得・設定以外にも、Getメソッド・Setメソッドによってもビット値を取得・設定することができます。 また、SetAllメソッドを使えば、BitArray内のすべてのビット値を同じ値にすることもできます。
ビット演算
BitArrayクラスでは、各種ビット演算に対応する以下のメソッドが用意されています。 引数に他のビット列を表すBitArrayを指定することで、そのBitArrayとの演算結果を求めることができます。
メソッド | 動作 |
---|---|
Notメソッド | すべての桁のビットを反転する |
Orメソッド | 指定されたBitArrayとの論理和を求める |
Andメソッド | 指定されたBitArrayとの論理積を求める |
Xorメソッド | 指定されたBitArrayとの排他的論理和を求める |
上記のメソッドによる演算では、メソッドを呼び出したインスタンス自身に演算結果が反映され、さらにインスタンス自身を戻り値として返します。 以下は、上記メソッドを使ってビット演算を行う例です。
シフト演算
BitArrayクラスでは、ビットシフトを行うメソッドとして、以下の2つのメソッドが用意されています。 ただし、このメソッドは.NET Standard 2.1/.NET Core 2.0以降でのみ使用できます。
メソッド | 動作 |
---|---|
LeftShiftメソッド | 左シフト演算を行う |
RightShiftメソッド | 右シフト演算を行う |
いずれのメソッドも、シフト量を引数で指定することができます。 このメソッドでは、シフトによって欠ける桁には常に0
が補われる論理シフトとして動作します。 符号ビットは存在しないものとされ、考慮されません。
要素の列挙順の都合により、シフト方向と実際にシフトされるビットの方向が逆になっています。
なお、回転シフト・循環シフトに相当する演算は用意されていません。 そのため、そのような操作を行う場合は独自に実装する必要があります。
その他のビット演算
先行する/後続する0のビット数 (LZCNT/TZCNT)
BitOperationsクラスでは、先行する・後続する0のビットの数を計上するLeadingZeroCountメソッド・TrailingZeroCountメソッドを使用することができます。
これと同様の演算を行うメソッドはBitArrayクラスには用意されていませんが、次のようにして実装することができます。
立っているビットの数 (POPCNT)
BitOperationsクラスでは、立っているビットの数(1のビットの数)を計上するPopCountメソッドを使用することができます。
これと同様の演算を行うメソッドはBitArrayクラスには用意されていませんが、次のようにして実装することができます。
ビット列の配列へのコピー
CopyToメソッドを使うと、BitArrayのビット列を配列にコピーすることができます。 このメソッドはコンストラクタと逆の動作をします。 つまり、int[]
やbyte[]
をコピー先とした場合は、ビット列の内容がそのままint・byteのビット列としてコピーされます。 bool[]
の場合は、各ビットの値が一つのbool値として配列にコピーされます。 これ以外の配列をコピー先とすることはできず、そういった配列を指定した場合は例外ArgumentExceptionがスローされます。
コピー先の配列のほかに、CopyToメソッドではコピー先のインデックスを指定します。 0
を指定すれば、配列の先頭にコピーします。
任意の桁数のビット列
BitArrayクラスでは、桁数を指定してビット列を作成できます。 このとき、桁数として2n以外や奇数を指定することもできます。 また、桁数に0を指定することもできます。 0を指定した場合でもArgumentOutOfRangeExceptionなどの例外はスローされません。
BitArrayとその他のクラス
BitArrayクラスでは、内部的には32ビット整数によって各ビットが管理されるようですが、直接整数型を使ってビット演算を行う場合に比べると若干のオーバーヘッドがあります。 ただ、例えば64ビット(long
)を超えるような長大な桁数のビット列や、2のべき乗でない桁数のビット演算を行いたい場合には多少の利点があります。
長大な桁数の数を扱いたい場合はBigInteger構造体を使うこともできます。 ただし、この構造体ではANDやORなどのビット演算を行うことはできません。 BigInteger構造体については多倍長整数型を参照してください。
数値や数値型配列のビット表現・バイト列を取得したい場合は、BufferクラスやBitConverterクラスを用いることができます。 詳しくはバイト列操作を参照してください。