2017-08-11 11 views
0

私が作業しているプロジェクトでは、関数内で乱数のベクトルを生成する必要があります。問題は、私は毎回同じベクトルを生成することになるということです。私は、ランダムな数字の配列が生成されますが、どうやら、それはどちらか動作しない関数にジェネレータを渡すことによってそれを解決しようとしていC++関数で乱数を生成する

#include <iostream> 
#include <random> 

std::vector<double> generate(std::default_random_engine generator, double mean, double sigma, int n) 
{ 
    std::vector<double> generated(n,0); 
    std::normal_distribution<double> distribution(mean,sigma); 
    for (int i = 0;i<n;i++) 
     generated[i] = distribution(generator); 
    return generated; 
} 
std::vector<double> generate(double mean, double sigma, int n) 
{ 
    std::vector<double> generated(n,0); 
    std::default_random_engine generator; 
    std::normal_distribution<double> distribution(mean,sigma); 
    for (int i = 0;i<n;i++) 
     generated[i] = distribution(generator); 
    return generated; 
} 

int main(int argc, char** argv) 
{ 
    // Read inputs 
    int nrolls = 20; // number of experiments 
    int ntimes = 50; 
    double mean = 100; 
    double sigma = 4; 
    bool useFunction(false); 
    if (argc>1) 
     useFunction=true; 

    // crates series 
    std::vector< std::vector<double> > results(ntimes,std::vector<double>()); 
    std::default_random_engine generator; 
    for (int i = 0;i<ntimes/4;i++){ 
     std::vector<double> generated(nrolls,0); 
     std::normal_distribution<double> distribution(mean,sigma); 
     for (int i = 0;i<nrolls;i++) 
      generated[i] = distribution(generator); 
     results[i] = generated; 
    } 
    for (int i = ntimes/4;i<ntimes/2;i++) 
     results[i] = generate(generator,mean,sigma,nrolls); 
    for (int i = ntimes/2;i<3*ntimes/4;i++){ 
     std::vector<double> generated(nrolls,0); 
     std::normal_distribution<double> distribution(mean,sigma); 
     for (int i = 0;i<nrolls;i++) 
      generated[i] = distribution(generator); 
     results[i] = generated; 
    } 
    for (int i = 3*ntimes/4;i<ntimes;i++) 
     results[i] = generate(mean,sigma,nrolls); 
    // 

    // Display all random numbers 
    for (int i = 0;i<ntimes;i++){ 
     std::cout<<i; 
     for (int j = 0;j<nrolls;j++) 
      std::cout<<" "<<results[i][j]; 
     std::cout<<std::endl; 
    } 

    // Check number of equal results 
    int n_equal(0); 
    int n_total(0); 
    for (int i=0;i<ntimes;i++){ 
     for (int k = 0;k<nrolls;k++){ 
      for (int j=i+1;j<ntimes;j++){ 
       n_total++; 
       if (results[i][k] == results[j][k]) 
        n_equal++; 
      } 
     } 
    } 
    std::cout<<n_equal<<"/"<<n_total<<std::endl; 

    // Exit 
    return 0; 
} 

:私は私の問題を再現し、この例を持っています。誰かが、私がgenerate関数を呼び出すたびに別の配列を取得するために、どうすればよいのかのヒントを教えてくれますか?

ありがとうございました。

+3

毎回異なる値を取得するようにエンジンをシードすることができます – CoryKramer

答えて

5

ここには2つの問題があります。最初

std::vector<double> generate(std::default_random_engine generator, double mean, double sigma, int n) 

PRNGをコピーしてコピーします。つまり、関数を呼び出すたびに、呼び出し元からジェネレータを変更しないので、同じシーケンスから開始することになります。

第二の問題は、あなたが同じ発電機に関数を呼び出すたびに再作成

std::vector<double> generate(double mean, double sigma, int n) 

です。これは、毎回同じシーケンスを作成する予定であるため、動作しません。

通常、2つのオプションがあります。関数にPRNGを渡すことができます。または関数内にstatic PRNGを宣言して、関数呼び出し間に存続するようにすることができます。

+0

私は自分の問題がPRNGから来ていると思っていましたが、その理由は分かりませんでした。どちらのソリューションも完璧に動作しています!助けてくれてありがとう! – apalomer

+0

@apalomer問題ありません。喜んで助ける – NathanOliver

0

これらのビットを使って演奏した後、私は新しいC++ランダムジェネレータにグローバル変数を使用することをお勧めしました。そして、乱数スイートごとに1つずつ用意する必要があります。したがって、(統計的にはほぼ:) 100%確実に配布を指定してください。

擬似ランダムジェネレータは、最後の計算で生成された数を次のものを生成するために保持するため、静的な獣です。