C++でランダムな数値を生成する
この投稿では、C++でランダムな数値を生成する方法について説明します。
1.使用する std::rand
関数
C++ で乱数を生成する最も簡単かつ一般的な方法は、 rand()
と srand()
機能。これらの関数は <cstdlib>
ヘッダーであり、C 標準ライブラリの一部です。の rand()
関数は範囲内の疑似乱数の整数を返します [0, RAND_MAX]
、 どこ RAND_MAX
少なくとも次の定数です 32767
.
The srand()
関数はシード値を設定します。 rand()
関数。電話しなかったら srand()
電話する前に rand()
、シード値は、呼び出したかのように設定されます。 srand(1)
。これは、プログラムを実行するたびに、同じ一連の乱数を取得することを意味します。 rand()
。これを避けるには、次のように呼び出す必要があります。 srand()
プログラムを実行するたびに異なるシード値を使用します。これを行う一般的な方法は、次のように現在時刻をシード値として使用することです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> #include <cstdlib> #include <ctime> int main() { srand(time(NULL)); int rand = std::rand(); std::cout << rand << std::endl; return 0; } |
The rand()
と srand()
機能は非常に使いやすく、理解しやすいです。ただし、注意すべき欠点がいくつかあります。
- The
rand()
関数は擬似乱数の整数を生成します。擬似ランダムとは、数値が真にランダムではなく、シード値に依存する決定論的アルゴリズムによって生成されることを意味します。 - The
rand()
関数は次の整数のみを生成できます。RAND_MAX
、一部のアプリケーションでは十分ではない可能性があります。のrand()
この関数も、次の倍数しか生成できないため、精度が低くなります。1/RAND_MAX
. - The
rand()
関数はアルゴリズムとして線形合同生成器 (LCG) を使用しますが、これには多くの欠陥と弱点があることが知られています。のrand()
また、この関数はランダム性が低く、数値間にパターンと相関があることを意味します。また、予測不可能性が低いため、数値の推測やリバース エンジニアリングが容易になります。
したがって、この関数は、乱数を生成する迅速かつ簡単な方法が必要な場合、および乱数の範囲、精度、品質、セキュリティをあまり気にしない場合にのみ使用する必要があります。
2. <random>
ヘッダ
C++ で乱数を生成するより良いオプションは、 <random>
ヘッダ。このヘッダーは、さまざまな機能とオプションを使用して乱数を生成するための最新かつ柔軟な方法を提供します。の <random>
ヘッダーは 4 つの主要コンポーネントで構成されます。
Engines:
これらは、疑似乱数を生成するためのさまざまなアルゴリズムを実装するクラスです。たとえば、エンジンの一部は次のとおりです。minstd_rand
(LCG)、mt19937
(メルセンヌ・ツイスター)、ranlux48
(ランラックス)などDistributions:
これらは、エンジンの出力をさまざまな範囲や形状に変換するクラスです。たとえば、ディストリビューションの一部は次のとおりです。uniform_int_distribution
(均一な整数)、normal_distribution
(通常またはガウス)、bernoulli_distribution
(ブール値) などSeeds:
これらは、エンジンを初期化または再シードする値です。任意の符号なし整数または符号なし整数の配列をシードとして使用できます。という特別なクラスを使用することもできます。random_device
ランダム性のハードウェア ソースから非決定的なシードを生成します。Variates:
これらは、エンジンとディストリビューションを組み合わせて、特定のアルゴリズムと形状に従って乱数を生成するオブジェクトです。エンジンとディストリビューションを引数としてコンストラクターまたは関数呼び出しに渡すことで、変数を作成できます。
この関数を使用するには、ニーズに合ったエンジンとディストリビューションを選択し、それらを使用して変量を作成し、それを呼び出して乱数を生成する必要があります。たとえば、次のコードは、メルセンヌ ツイスター エンジンと一様な整数分布を使用してランダムな整数を生成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> #include <random> int main() { std::mt19937 gen; gen.seed(std::random_device()()); std::uniform_int_distribution<std::mt19937::result_type> dist; std::cout << dist(gen) << std::endl; return 0; } |
使用する代わりに std::random_device
、使用できます クロノライブラリ ランダムナンバーエンジンのシードを取得する mersenne_twister_engine
。例えば:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> #include <random> #include <chrono> int main() { unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::mt19937 gen(seed); std::uniform_int_distribution<std::mt19937::result_type> dist; std::cout << dist(gen) << std::endl; return 0; } |
The <random>
ヘッダーには、 rand()
と srand()
機能:
- より広い範囲と精度を備えています。の
<random>
ヘッダーは、unsigned int 型の最大値までの整数を生成できます。通常、これは4294967295
. - より高い品質と安全性を備えています。の
<random>
header は、LCG よりも優れたアルゴリズムを備えたさまざまなエンジンを提供します。rand()
. - より柔軟性と汎用性が高くなります。の
<random>
ヘッダーを使用すると、さまざまなエンジンとディストリビューションから選択して、さまざまな形状とプロパティの乱数を生成できます。
3.使用する Boost.Random
図書館
C++ で乱数を生成する 3 番目のオプションは、使用することです。 Boost.Random
ライブラリ。これは Boost C++ ライブラリ コレクションの一部です。と同様の機能を提供します。 <random>
ヘッダーですが、より多くのエンジンとディストリビューションから選択できます。エンジンの一部は次のとおりです。 knuth_b
(シャッフル順序)、 lagged_fibonacci
(遅行フィボナッチ) など。分布の一部は次のとおりです。 lognormal_distribution
(対数正規)、 cauchy_distribution
たとえば、次のコードは、次のコード間のランダムな整数を生成します。 1
と 10
を使用して Boost.Random
図書館:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> #include <boost/random.hpp> int main() { // ランダムなデバイス シードを使用してメルセンヌ ツイスター エンジンを作成します boost::random::mt19937 engine(boost::random::random_device{}()); // 1 から 10 までの一様な整数分布を作成します boost::random::uniform_int_distribution<int> dist(1, 10); // エンジンとディストリビューションを使用して変数を作成します boost::random::variate_generator<boost::random::mt19937&, boost::random::uniform_int_distribution<int>> variate(engine, dist); // 乱数を生成して出力します int random = variate(); cout << random << endl; return 0; } |
これで、C++で乱数を生成できます。