Angry Shoe と peterchen の優れた回答を、2015 年の最新技術の概要で補足したいと思います。
いくつかの良い選択
randutils
randutilsライブラリ(プレゼンテーション)は興味深い目新しさであり、シンプルなインターフェイスと (宣言された) 堅牢なランダム機能を提供します。プロジェクトへの依存を追加するという欠点があり、新しいため、広範囲にテストされていません。とにかく、無料 (MIT ライセンス) でヘッダーのみなので、試してみる価値はあると思います。
最小サンプル: サイコロ
#include <iostream>
#include "randutils.hpp"
int main() {
randutils::mt19937_rng rng;
std::cout << rng.uniform(1,6) << "\n";
}
ライブラリに興味がなくても、Web サイト ( http://www.pcg-random.org/ ) には、乱数生成全般、特に C++ ライブラリに関する興味深い記事がたくさんあります。
Boost.Random
Boost.Random (ドキュメンテーション)は、インターフェースの多くを共有するC++11のに影響を与えたライブラリです。<random>理論的には外部依存関係でもありBoostますが、現在では「準標準」ライブラリのステータスを持ち、そのRandomモジュールは高品質の乱数生成のための古典的な選択肢と見なすことができます. C++11このソリューションには、次の 2 つの利点があります。
- 移植性が高く、C++03 のコンパイラ サポートが必要なだけです
random_deviceシステム固有の方法を使用して、高品質のシードを提供します
唯一の小さな欠陥は、モジュールの提供random_deviceがヘッダーのみではなく、コンパイルしてリンクする必要があることboost_randomです。
最小サンプル: サイコロ
#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>
int main() {
boost::random::random_device rand_dev;
boost::random::mt19937 generator(rand_dev());
boost::random::uniform_int_distribution<> distr(1, 6);
std::cout << distr(generator) << '\n';
}
最小限のサンプルはうまく機能しますが、実際のプログラムでは 2 つの改善点を使用する必要があります。
- make
mt19937a thread_local: ジェネレーターは非常に充実しており (> 2 KB)、スタックに割り当てないほうがよい
mt19937複数の整数を持つシード: メルセンヌ ツイスターには大きな状態があり、初期化中により多くのエントロピーを利用できます
あまり良くない選択肢
C++11 ライブラリ
ライブラリは最も慣用的なソリューション<random>ですが、基本的なニーズに対してさえ、そのインターフェースの複雑さと引き換えに多くを提供するものではありません. 欠陥は次のとおりです。標準は、その出力に最小限の品質を義務付けておらず ( を返すstd::random_device限り)、2015 年現在、MinGW (最も使用されているコンパイラではありませんが、ほとんど難解な選択ではありません) は常に最小限のサンプルに出力されます。entropy()04
最小サンプル: サイコロ
#include <iostream>
#include <random>
int main() {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(1, 6);
std::cout << distr(generator) << '\n';
}
実装が腐っていない場合、このソリューションは Boost のソリューションと同等であり、同じ提案が適用されます。
ゴドーの解
最小サンプル: サイコロ
#include <iostream>
#include <random>
int main() {
std::cout << std::randint(1,6);
}
これは、シンプルで効果的できちんとしたソリューションです。唯一の欠陥です。コンパイルにはしばらく時間がかかります。C++17 が予定どおりにリリースされ、実験的なrandint機能が新しい標準に承認された場合、約 2 年かかります。おそらくその時までに、播種品質の保証も改善されるでしょう.
最小サンプル: サイコロ
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr));
std::cout << (std::rand() % 6 + 1);
}
古いCソリューションは有害であると考えられており、正当な理由があります(他の回答はこちらまたは詳細な分析を参照してください)。それでも、それには利点があります: シンプルで、ポータブルで、高速で正直です。つまり、得られる乱数はまともなものではないことがわかっているため、それらを深刻な目的に使用したくありません。
アカウンティング トロール ソリューション
最小サンプル: サイコロ
#include <iostream>
int main() {
std::cout << 9; // http://dilbert.com/strip/2001-10-25
}
9 は通常のダイスロールではやや珍しい結果ですが、このソリューションの優れた品質の優れた組み合わせに感心する必要があります。9 を 4 に置き換えることで、あらゆる種類のダンジョンズ アンド ドラゴンズ ダイの完全なジェネレーターが得られますが、シンボルを含む値 1、2、および 3 は回避されます。このプログラムは、実際には未定義の動作を引き起こします。