A random number engine is an object that produces a sequence of pseudorandom numbers of unsigned type. It remembers an internal state and advances the state to produce the next number whenever it is called. In C++, the most common engine is std::mt19937.
Before the engine can be used, it must be seeded. A convenient object to generate seeds with is std::random_device.
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
// Initialize eng with the value returned by rd
std::mt19937 eng{ rd() };
std::cout << eng() << '\n';
}
The object rd is a random_device object. Calling rd() returns an unsigned integer value, which is used to seed the mt19937 engine eng. The subsequent expression eng() returns the next pseudorandom number from the engine, which gets sent to standard output. Each time you run the program, it should produce a different number because the value of rd() is itself non deterministic.
If you would like a reproducible random sequence, you simply supply a fixed seed:
#include <iostream>
#include <random>
int main()
{
// Use a fixed seed to make the generated sequence repeatable
std::mt19937 eng{ 42 };
std::cout << eng() << '\n';
std::cout << eng() << '\n';
}
The engine eng is now initialized with the seed value of 42. The first call eng() returns one pseudorandom number, and the next call returns the following pseudorandom number from the sequence. Each time you execute this program, you should always see the same two numbers because the seed never changes.
A pseudorandom engine returns pseudorandom numbers spanning the whole of its result_type. For mt19937, the result_type is a 32 bit unsigned integer. We don't really want any pseudorandom number, only the numbers that fall within a specific range.
It is the distribution that will perform this range adjustment; the engine itself is responsible for nothing more than providing the basic sequence of numbers.
This makes it very useful for situations in which we want a full width range or simply want the raw bits.
What if you don't supply a seed value after constructing your engine? Then it has a certain default seed, and thus the pseudorandom sequence is determined and runs the same each time. That is usually not what we want from our pseudorandom streams when writing code for any serious purpose, but if you are happy to have non deterministic sequences each time you run the program, just remember the first step: seed your engine.
Engines are copyable. If you take a copy, then you will have a pseudorandom stream that has the same initial state and produces exactly the same sequence as the original stream.
Changing one does not affect the other at all. That can be surprisingly useful.
0 comments
No comments yet. Be the first.