タイトルが示すように、新しいC++ 11 <random>
ライブラリを使用して乱数を生成する方法を見つけようとしています。私はこのコードで試しました:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
私が持っているコードの問題は、コンパイルして実行するたびに、常に同じ数値が生成されることです。だから私の質問は、ランダムライブラリの他のどの機能が本当にランダムでありながらこれを達成できるのでしょうか?
私の特定のユースケースでは、[1, 10]
の範囲内の値を取得しようとしていました
MicrosoftのStephan T. Lavavej(stl)がGoing Nativeで、新しいC++ 11ランダム関数の使用方法と、Rand()
を使用しない理由について講演しました。その中に、彼は基本的にあなたの質問を解決するスライドを含めました。下のスライドからコードをコピーしました。
ここで彼の完全な講演を見ることができます: http://channel9.msdn.com/Events/GoingNative/2013/Rand-Considered-Harmful
#include <random>
#include <iostream>
int main() {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(1.0, 10.0);
for (int i=0; i<16; ++i)
std::cout << dist(mt) << "\n";
}
random_device
を1回使用して、mt
という名前の乱数ジェネレーターをシードします。 random_device()
はmt19937
よりも遅いですが、オペレーティングシステム(たとえば、 RdRand などのさまざまな場所からのソース)からランダムデータを要求するため、シードする必要はありません。
この質問/回答 を見ると、uniform_real_distribution
が[a, b)
の範囲で[a, b]
の範囲の数値を返すようです。それを行うには、uniform_real_distibution
は実際には次のようになります。
std::uniform_real_distribution<double> dist(1, std::nextafter(10, DBL_MAX));
私の「ランダム」ライブラリは、C++ 11のランダムクラスの便利なラッパーを提供します。簡単な「get」メソッドでほとんどすべてのことができます。
例:
範囲内の乱数
auto val = Random::get(-10, 10); // Integer
auto val = Random::get(10.f, -10.f); // Float point
ランダムブール
auto val = Random::get<bool>( ) // 50% to generate true
auto val = Random::get<bool>( 0.7 ) // 70% to generate true
Std :: initilizer_listからのランダムな値
auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
イテレータ範囲またはすべてのコンテナからのランダムイテレータ
auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator
auto it = Random::get( vec ); // return random iterator
そしてさらに多くのもの! githubページをご覧ください。
これらのラインに沿って書いたものを次に示します。
#include <random>
#include <chrono>
#include <thread>
using namespace std;
//==============================================================
// RANDOM BACKOFF TIME
//==============================================================
class backoff_time_t {
public:
random_device rd;
mt19937 mt;
uniform_real_distribution<double> dist;
backoff_time_t() : rd{}, mt{rd()}, dist{0.5, 1.5} {}
double Rand() {
return dist(mt);
}
};
thread_local backoff_time_t backoff_time;
int main(int argc, char** argv) {
double x1 = backoff_time.Rand();
double x2 = backoff_time.Rand();
double x3 = backoff_time.Rand();
double x4 = backoff_time.Rand();
return 0;
}
〜
疑似乱数ジェネレーターについて読むことができるリソースを次に示します。
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
基本的に、コンピューターの乱数にはシードが必要です(この数値は現在のシステム時刻になります)。
交換
std::default_random_engine generator;
によって
std::default_random_engine generator(<some seed number>);