std::bitset 使い方のメモ
2020-03-24
たまに使おうとするとアレどうやるんだったっけってなるので使い方を雑にまとめておく。
はい
概要
ビットの集合を表すクラス。便利な機能がついた、boolean の固定長配列のようなもの。
ビットを使った処理を整数型とビット演算だけでゴリっと書くよりもコードが直感的に読みやすくなる。
例えば、任意の整数値をビット列に変換したり、i番目のビットが立ってるかどうかの判定をしたり、ビットの合計をカウントしたりみたいなことが簡単にできる。
以下C++のバージョンは14で、任意のコード例は基本的に通称 575 こと
using namespace std
してる前提で書いていく。
ヘッダ
#include <bitset>
生成および初期化
ポイント🧐
まずテンプレート引数でサイズ(総ビット数)を指定する。
このとき指定したサイズは、動的に後から変更したりできないので注意。
コンストラクタ その1
総ビット数がNのbitsetを生成するコンストラクタ。この方法の場合最初は全ビット0になる。あんまり使ったことない。
bitset<N> bits;
コンストラクタ その2(重要)
任意の整数値を元にインスタンスを生成する。
下の例の場合、整数9から長さ5のビット列を生成する。
一番よく使う。というかほぼこれしか使ったことない。
bitset<5> bits(9); // 01001
コンストラクタ その3
二進数を表現した文字列を元にインスタンスを生成する。
下の例の場合、9を二進数で表現した文字列からbitsetを生成する。
bitset<5> bits("01001"); // 01001
文字列は二進数を表現したものでなければダメで、'0'
または'1'
以外の文字が含まれていた場合は例外がスローされる。
補足として、真を表す文字と偽を表す文字を受け取るコンストラクタもあって、それを使うと 0|1 以外の組み合わせの文字列からもインスタンス生成できる。(けど使ったことはない。)
入出力
cin
と cout
で入出力できる。(cout はちょっとデバッグしたりするときに地味に便利?)
cin で二進表記の文字列を入力、cout は二進表記の文字列を出力する。
int main() {
bitset<5> bits;
cin >> bits;
cout << bits << endl;
return 0;
}
1001 # 入力
01001 # 出力
なお、入力は二進表記でなければいけないので整数値を受け取ったりはできないことに注意。
9 # 入力(二進表記でないのでダメ)
00000 # 出力
アクセス(重要)
一番キモの部分。
bitset
の i
ビット目にアクセスするには []
演算子 を使う。
取得も設定もできる。
注意点として、i
が bitset
のサイズを超えていても例外とか投げないので必ずサイズを超えないようにする必要がある。
int main() {
bitset<5> bits(9); // 01001
cout << bits[0] << endl; // 1
cout << bits[1] << endl; // 0
cout << bits[2] << endl; // 0
cout << bits[3] << endl; // 1
cout << bits[4] << endl; // 0
bits[1] = 1;
bits[2] = true;
cout << bits[1] << endl; // 1
cout << bits[2] << endl; // 1
return 0;
}
整数型とビット演算で i
ビット目が立ってるか確認する場合、if (bitmask >> i & 1)
みたいな判定をしたりするけどこれが bitset
なら if (bits[i])
と簡潔にかける。わかりやすくてよい。😇
ちなみに test
というメンバ関数がある。bits.test(i)
みたいな感じで i
ビット目を取得できる。
std::vector
でいうところのat
みたいなヤツ。
[]
演算子との違いとしては、test
のほうは範囲外を参照しようとしたときにちゃんと例外を投げてくれる。なのでこっちのほうが安全。
あと、set
というメンバ関数もある。bits.set(i, true)
または bits.set(i, false)
のように、i
ビット目のフラグをセットできる。test
と同じように例外を投げてくれる。
だけど競プロとかではわざわざそこまでしなくてより短く書ける []
演算子のほうを良く使う、、、と思う。
ビット演算
もろもろ演算子オーバーロードされていて、たいだいのことはできる。
&
, |
, ^
, ~
, &=
, |=
, ^=
など。あとビットシフト <<
, >>
, <<=
, >>=
もちゃんとある。
お役立ちメンバ関数など
count
(ちょっと重要)
立っているビットの合計をカウントしてくれるメンバ関数。
競プロでは、よく __builtin_popcount
っていう gcc でしか使えないやつが使われているのを見るけどそれの bitset
版みたいな感じ。
flip
全ビットを反転するメンバ関数。
to_ullong
ビット列を unsigned long long
型に変換して返してくれるメンバ関数。
これの int
版とかはないっぽいので、手っ取り早く整数にしたかったらたぶんこれを使う事になると思う。
to_string
文字通り、ビット列を文字列に変換して返してくれるメンバ関数。
all
全ビットが1かどうかを判定するすメンバ関数。
any
一つ以上1なビットがあるかを判定するすメンバ関数。
none
全ビットが0かどうかを判定するすメンバ関数。
以上。より詳細はリファレンスを読みましょう。
オワリ😇