简体   繁体   中英

C++ Generating random numbers in functions

For a project that I am working on I need to generate a vector of random numbers within a function. The problem is that I end up generating the same vector of numbers each time. I have this example that reproduces my problem:

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

I have tried to solve it by passing the generator to the function where the array of random numbers is generated but apparently, it does not work either. Can somebody give me a hint on how should I do it to get different arrays each time i call the generate function?

Thank you very much.

You have two problems here. First

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

Takes the PRNG by value, which means it makes a copy. That means every time you call the function your going to be starting from the same sequence since you never modify the generator from the call site.

The second issue is with

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

You recreate the same generator every time you call the function. This is not going to work as it is going to create the same sequence each time.

Typically you have two options. You can pass the PRNG to the function by reference, or you declare a static PRNG in the function so it persists between function calls.

After playing a bit with them, I found it best to use global variables for the new C++ random generators. And you should have one per random number suite, so you're (statistically almost :) 100% sure to get the distribution specified.

Pseudo-random generators are static beasts by nature, since they keep numbers generated in the last computation to generate the next.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM