2017-08-11 183 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; 
} 

我曾嘗試通過將發電機到產生隨機數的數組,但顯然,這也不行功能來解決這個問題。有人可以給我一個暗示,我應該怎麼做,每次我調用生成函數時獲得不同的數組?

非常感謝。

+3

您可以讓您的引擎每次獲得不同的值 – CoryKramer

回答

5

這裏有兩個問題。第一

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) 

你每次調用該函數時創建相同的發電機。這不會起作用,因爲它每次都會創建相同的序列。

通常你有兩個選擇。您可以通過引用將PRNG傳遞給函數,也可以在函數中聲明PRNG,以便在函數調用之間持續存在。

+0

我認爲我的問題來自PRNG,但只是不知道爲什麼。這兩種解決方案都工作得很好!非常感謝你的幫助!! – apalomer

+0

@apalomer沒問題。樂意效勞 – NathanOliver

0

在和他們玩了一下之後,我發現最好爲全新的C++隨機生成器使用全局變量。你應該有一個隨機數套件,所以你(統計上幾乎:) 100%肯定會得到指定的分佈。

僞隨機生成器本質上是靜態的,因爲它們保留上次計算中生成的數字以生成下一個。