161

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

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

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

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

4

6 に答える 6

238

Microsoft の Stephan T. Lavavej(stl) は、Going Native で、新しい C++11 ランダム関数の使用方法と使用しない理由について講演しましたrand()。その中に、彼は基本的にあなたの質問を解決するスライドを含めました。以下のスライドからコードをコピーしました。

ここで彼の完全な講演を見ることができます:

#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という名前の乱数ジェネレーターをシードするために一度使用し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));
于 2013-10-29T18:48:05.840 に答える
0

ここに私がちょうどそれらの行に沿って書いたものがあります::

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

于 2016-12-21T02:44:02.063 に答える
-3

2 つの一般的な状況があります。1 つ目は、乱数が必要であり、品質や実行速度にあまりこだわらないことです。その場合は、次のマクロを使用します

#define uniform() (rand()/(RAND_MAX + 1.0))

これにより、0 から 1 - イプシロンの範囲の p が得られます (RAND_MAX が double の精度よりも大きい場合を除きますが、それについて心配する必要はありません)。

int x = (int) (uniform() * N);

0 から N -1 までのランダムな整数を与えるようになりました。

他の分布が必要な場合は、p を変換する必要があります。または、uniform() を数回呼び出す方が簡単な場合もあります。

繰り返し可能な動作が必要な場合は、定数でシードします。それ以外の場合は、time() の呼び出しでシードします。

品質や実行時のパフォーマンスが気になる場合は、uniform() を書き直してください。ただし、それ以外の場合はコードに触れないでください。0 から 1 マイナス イプシロンに常に uniform() を保持します。C++ 乱数ライブラリをラップしてより優れた uniform() を作成できるようになりましたが、これは一種の中レベルのオプションです。RNG の特性が気になる場合は、基礎となるメソッドがどのように機能するかを理解するために少し時間を費やしてから提供することも価値があります。したがって、コードを完全に制御でき、同じシードを使用すると、プラットフォームやリンク先の C++ のバージョンに関係なく、シーケンスが常にまったく同じになることを保証できます。

于 2016-10-10T12:37:16.103 に答える