web-dev-qa-db-ja.com

C ++ 11ランダムライブラリを使用して乱数を生成する

タイトルが示すように、新しいC++ 11 <random>ライブラリを使用して乱数を生成する方法を見つけようとしています。私はこのコードで試しました:

std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);

私が持っているコードの問題は、コンパイルして実行するたびに、常に同じ数値が生成されることです。だから私の質問は、ランダムライブラリの他のどの機能が本当にランダムでありながらこれを達成できるのでしょうか?

私の特定のユースケースでは、[1, 10]の範囲内の値を取得しようとしていました

122
smac89

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));
173
Bill Lynch

私の「ランダム」ライブラリは、C++ 11のランダムクラスの便利なラッパーを提供します。簡単な「get」メソッドでほとんどすべてのことができます。

例:

  1. 範囲内の乱数

    auto val = Random::get(-10, 10); // Integer
    auto val = Random::get(10.f, -10.f); // Float point
    
  2. ランダムブール

    auto val = Random::get<bool>( ) // 50% to generate true
    auto val = Random::get<bool>( 0.7 ) // 70% to generate true
    
  3. Std :: initilizer_listからのランダムな値

    auto val = Random::get( { 1, 3, 5, 7, 9 } ); // val = 1 or 3 or...
    
  4. イテレータ範囲またはすべてのコンテナからのランダムイテレータ

    auto it = Random::get( vec.begin(), vec.end() ); // it = random iterator
    auto it = Random::get( vec ); // return random iterator
    

そしてさらに多くのもの! githubページをご覧ください。

https://github.com/effolkronium/random

19
Ilya Polishchuk

これらのラインに沿って書いたものを次に示します。

#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;
}

2
Bill Moore

疑似乱数ジェネレーターについて読むことができるリソースを次に示します。

https://en.wikipedia.org/wiki/Pseudorandom_number_generator

基本的に、コンピューターの乱数にはシードが必要です(この数値は現在のシステム時刻になります)。

交換

std::default_random_engine generator;

によって

std::default_random_engine generator(<some seed number>);