I am exercising the random library, new to C++11. I wrote the following minimal program:
#include
#include
using namespace st
#include
#include
using namespace std;
int main() {
std::random_device r; // 1
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; // 2
std::mt19937 eng(seed); // 3
uniform_real_distribution urd(0, 1);
cout << "Uniform [0, 1): " << urd(eng);
}
In order to get unpredictable results from a pseudo-random number generator
we need a source of unpredictable seed data. On 1 we create a
std::random_device for this purpose. On
2 we use a std::seed_seq to combine
several values produced by random_device into a form suitable for seeding a
pseudo-random number generator. The more unpredictable data that is fed into
the seed_seq, the less predictable the results of the seeded engine will
be. On 3 we create a random number engine using the seed_seq to seed the
engine's initial state.
A seed_seq can be used to initialize multiple random number engines;
seed_seq will produce the same seed data each time it is used.
Note: Not all implemenations provide a source of non-deterministic data.
Check your implementation's documentation for std::random_device.
If your platform does not provide a non-deterministic random_device then some other sources can be used for seeding. The article Simple Portable C++ Seed Entropy suggests a number of alternative sources:
std::chrono::high_resolution_clock (time() typically has a resolution of one second which generally too low)For example:
#include
#include
#include
#include
#include
using namespace std;
// we only use the address of this function
static void seed_function() {}
int main() {
// Variables used in seeding
static long long seed_counter = 0;
int var;
void *x = std::malloc(sizeof(int));
free(x);
std::seed_seq seed{
// Time
static_cast(std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count()),
// ASLR
static_cast(reinterpret_cast(&seed_counter)),
static_cast(reinterpret_cast(&var)),
static_cast(reinterpret_cast(x)),
static_cast(reinterpret_cast(&seed_function)),
static_cast(reinterpret_cast(&_Exit)),
// Thread id
static_cast(
std::hash()(std::this_thread::get_id())),
// counter
++seed_counter};
std::mt19937 eng(seed);
uniform_real_distribution urd(0, 1);
cout << "Uniform [0, 1): " << urd(eng);
}