私の要件は、ランダムなバイトのデータ(乱数ではない)、別名一様分布ビットを生成することです。
そのため、C++ 11/14ランダム機能を使用してこれを行う正しい/効率的な方法は何であるか疑問に思いました。私は例を見回しましたが、それらはall数の生成に焦点を合わせているようです(ints、floatsなど)
私が使用している現在のソリューションは次のとおりです。
#include <vector>
#include <random>
int main()
{
std::random_device rd;
std::uniform_int_distribution<int> dist(0,255);
std::vector<char> data(1000);
for (char& d : data)
{
d = static_cast<char>(dist(rd) & 0xFF);
}
return 0;
}
分布はランダムなビットを取り、それらを数値に変換します。実際にランダムビットが必要な場合は、エンジンを使用します。
特に、これらの要件は、可能な各ビット値が均一に発生する可能性が高いビットのシーケンスを生成するタイプおよびオブジェクトのアルゴリズムインターフェイスを指定します。3
URNGオブジェクトへの1回の呼び出しで、多くの(通常は32以上の)ビットを生成および配信でき、これらのビットを符号なし整数型の単一のパッケージ値として返します。4N3847
random_device
は、一様分布のビットに簡単にアクセスできるように指定されています。
std::random_device engine;
unsigned x = engine(); // sizeof(unsigned) * CHAR_BIT random bits
他のエンジンでは、result_typeが保持できるよりも少ないビットを返すため、または小数ビットを効果的に返すことによって、random_device
ほど均一にランダムなビットを取得するのはそれほど簡単ではない場合があることに注意してください。
unsigned
のサイズが実装で定義されているため、random_device
が実装で定義されたビット数を返すことが懸念される場合は、十分なビットを収集してから提供するアダプターを作成できます。十分なビットを提供し、残りを次のリクエストのためにキャッシュします。 (これを実行して、前述の問題を示す他のエンジンを処理することもできます。)
あなたが探しているのは _std::independent_bits_engine
_ アダプターです:
_#include <vector>
#include <random>
#include <climits>
#include <algorithm>
#include <functional>
using random_bytes_engine = std::independent_bits_engine<
std::default_random_engine, CHAR_BIT, unsigned char>;
int main()
{
random_bytes_engine rbe;
std::vector<unsigned char> data(1000);
std::generate(begin(data), end(data), std::ref(rbe));
}
_
一般的なケースでは、受け入れられた答えは厳密には正しくないことに注意してください。ランダムエンジンは、範囲[min()
、max()
]に属する符号なしの値を生成しますが、これは必ずしもすべての可能な値をカバーするとは限りません。結果タイプ(たとえば、std::minstd_Rand0::min() == 1
)であるため、エンジンを直接使用すると、均一に分散されないランダムなバイトが取得される可能性があります。ただし、_std::random_device
_の場合、範囲は[std::numeric_limits<result_type>::min()
、std::numeric_limits<result_type>::max()
]であるため、この特定のエンジンはアダプターがなくてもうまく機能します。
あなたの質問に答えるために:あなたはできません。
この標準では、_std::uniform_int_distribution
_をchar
、_signed char
_、または_unsigned char
_でテンプレート化することは許可されていません。これは規格の欠陥であると考える人もいますが、実際はそうです。
_std::uniform_int_distribution
_で_unsigned short
_をテンプレート化し、その最小/最大範囲をstd::numeric_limits<unsigned char>::min()
およびstd::numeric_limits<unsigned char>::max()
に設定して、結果を_unsigned char
_。
標準から:
この26.5節全体を通して、テンプレートをインスタンス化する効果は次のとおりです。
[...]
e)
IntType
という名前のテンプレートタイプパラメータを持つものは、対応するテンプレート引数がcvで修飾されておらず、short
、int
、long
のいずれかでない限り、未定義です。 、_long long
_、_unsigned short
_、_unsigned int
_、_unsigned long
_、または_unsigned long long
_。§26.5.1.1[Rand.req.genl]
さらに:
実際にランダムバイトを生成するには、 _std::mt19937
_ を使用する必要があります。 _std::random_device
_は遅くなる傾向があり、必要のない統計的特性(つまり、暗号化での使用に適している)を備えたエントロピーを生成する可能性があります。
そうは言っても、_std::mt19937
_をシードする必要があります。これは、_std::random_device
_および _std::seed_seq
_ を使用して実行できます。
_std::seed_seq
_を使用して_std::mt19937
_をシードしない場合、_std::mt19937
_の内部状態には多くのゼロが残るため、かなりの時間がかかることに注意してください。 「ウォームアップ」しながら。
「ウォームアップ」の詳細については、 ここを参照 。