简体   繁体   中英

Random number from normal distribution in C++

As a complete beginner to C++, I would like to generate a random number from a normal distribution.

With the following code (derived from this post ), I am able to do so:

#include <iostream>   
#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>

using namespace std;

int main()
{
    boost::mt19937 rng(std::time(0)+getpid());
    boost::normal_distribution<> nd(0.0, 1.0);
    boost::variate_generator<boost::mt19937&,
                             boost::normal_distribution<> > rnorm(rng, nd);

    cout<< rnorm();
  return 0;
}

Since the code is quite elaborate (in my view), I thought that there might be a more straightforward solution:

#include <iostream>
#include <random>

using namespace std;

int main()
{   
    default_random_engine generator;
    normal_distribution<double> distribution(0.0,1.0);

    cout << distribution(generator);
    return 0;
}

While I can generate a random number, it is continuously the same number. That leads to two questions:

(1) Why is that happing and how do I fix this?

(2) Is there another easier way to generate random numbers?

Use a seed to initialize your generator . Here I am using a time-based seed.

#include <iostream>
#include <random>
#include <chrono>

using namespace std;

int main()
{
    unsigned seed = chrono::system_clock::now().time_since_epoch().count();
    default_random_engine generator(seed);
    normal_distribution<double> distribution(0.0, 1.0);

    cout << distribution(generator);
    return 0;
}

(1) Why is that happing and how do I fix this?

It's happening because you default construct your PRNG (pseudo random number generator) and don't seed it. A PRNG generates a deterministic sequence of numbers. The sequence is typically very long and then it starts all over again. The seed is used to set the internal state of the PRNG - its starting point so to speak. Given no seed, it'll start with the same state every time.

(2) Is there another easier way to generate random numbers?

No, not using modern standard C++ (C++11 and later).

Some notes:

  • Using a time based seed based on a one-shot sample of the clock is considered bad since you risk seeding two PRNG:s with the same value.
  • You only need one PRNG (per thread that needs to generate random numbers) in you program - and seeding a PRNG is considered costly (in terms of speed). You could therefore make the generator global so it can be used everywhere in the program. The below is a thread safe version, initialized with what is supposed to be a True (but slow) RNG , generating numbers from an entropy pool, std::random_device .
     std::mt19937& prng() { // extern declared in a header file static thread_local std::mt19937 gen(std::random_device{}()); return gen; }
  • If your random_device lacks entropy or is buggy (older versions of MinGW had a buggy implementation) you can combine random_device output with a few time based numbers (sampled some time apart) to create astd::seed_seq that you use to initialize your PRNG. The below should work with both buggy and conformant implementations to create a seed that is hard to predict:

     #include <chrono> #include <thread> // Create a seed_seq with 2 time based numbers and 2 random_device numbers. // The two sleeps are done to ensure some diff in the clock counts. static std::seed_seq get_seed() { static constexpr auto min = std::chrono::steady_clock::duration::min(); std::random_device rd; std::uint_least32_t si[4]; for(size_t s = 0; s < std::size(si);) { si[s++] = rd(); std::this_thread::sleep_for(min); si[s++] = static_cast<std::uint_least32_t>( std::chrono::steady_clock::now().time_since_epoch().count()); std::this_thread::sleep_for(min); } return {si[0], si[1], si[2], si[3]}; } std::mt19937& prng() { // extern declared in a header file static thread_local std::seed_seq seed = get_seed(); static thread_local std::mt19937 gen(seed); return gen; }

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