3

I was looking at the example for generating normal distributed random numbers at cppreference.com and refactored the code a bit to get this:

#include <iostream>
#include <random>

struct MyNormalDistribution {
    static double getRandomNumber(double mean,double std_dev){
        return std::normal_distribution<>(mean,std_dev)(MyNormalDistribution::generator);
    }
    private:
        static std::random_device rand;
        static std::mt19937 generator;
};
std::random_device MyNormalDistribution::rand;
std::mt19937 MyNormalDistribution::generator = std::mt19937(MyNormalDistribution::rand());

int main(int argc, char *argv[]) {
    for (int t=0;t<10;t++){
        std::cout << MyNormalDistribution::getRandomNumber(0,10) << std::endl;
    }
}

However, whenever I run this I get the same sequence of numbers. Is there some stupid mistake, or does the example on cppreference not include proper seeding?

How to I properly seed MyNormalDistribution ?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 4
    http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/seed – πάντα ῥεῖ Apr 16 '16 at 10:38
  • Most platform/systems have a cryptographically secure pseudo-random number generator ([CSPRNG](https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator)) that while not a true RNG they are essentially non-deterministic. They do not need to be seeded by a user and have entropy added on a continuing basis based on system radom occurrences. – zaph Jun 19 '16 at 15:20

2 Answers2

1

As it's written in cppreference.com, the "problem" is in your std::random_device:

std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.

In other words, I think you're using Linux OS and you don't have the 'CONFIG_HW_RANDOM' option set in your kernel. As alternative, you can just use another source of seeding value such as the system clock.

auto seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937 generator {seed};
Stamen Rakov
  • 456
  • 4
  • 10
0

One can seed the generator for example with the current time :

#include <iostream>
#include <random>

struct MyGenerator {
    std::mt19937 gen;
    static std::random_device rand;
    MyGenerator() : generator(rand()){ gen.seed(time(0)); }
};
std::random_device MyGenerator::rand;
struct MyNormalDistribution {
    static double getRandomNumber(double mean,double std_dev){
        return std::normal_distribution<>(mean,std_dev)(MyNormalDistribution::gen.gen);
    }
    private:
        static MyGenerator gen;
};
MyGenerator MyNormalDistribution::gen;
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 1
    The current time is a horrible seed. The clock may be manipulated, multiple processed starting within the clock resolution will get the same seed etc. As part of the input to `std::seed_seq`, current time is ok (if combined with more sources) and that sequence can then finally be used to seed the generator. But don't use raw time to seed a generator directly - please. – Jesper Juhl Apr 16 '16 at 13:33
  • @JesperJuhl what should I do to fix it ? add some offset? – 463035818_is_not_an_ai Apr 16 '16 at 17:06
  • 1
    For many uses using the raw time as seed is perfectly OK. One needs to understand when and where we have to ditch simple things and start using complicated things. E.g. if you want to perform Monte Carlo integration, don't require replicability of results and don't use multiple threads started very close to each other in time, then using `time(0)` as seed is perfectly acceptable. – quant_dev Aug 26 '18 at 20:05