I'm learning about the library, which improves on the old rand and srand in many ways. But with the rand it's clear that there is one and only one random number generator that gets called and updated whenever rand is used, wherever that is in your program. With the new way I'm not sure how to imitate this behaviour efficiently and with good style. For instance what if I want a dice roll and, aping online examples written in the main procedure, I write an object with a method like this:
class foo{
public:
float getDiceRoll(){
std::random_device rd;
std::default_random_engine e1(rd());
std::uniform_int_distribution<int> uniform_dist(1, 6);
return uniform_dist(e1);
}
}
This looks terrible because the engine is re-created every time you want a dice roll. This is a bit of a contrived case, but in a large program you are going to have to put the declaration of the random number generator somewhere. As a first attempt to use I just want there to be one generator for all random numbers, like in the old days. What is the nicest way to achieve this? Easily available examples online are all written straight into the main procedure and so they do not answer this basic question. I cannot think of anything that doesn't seem like taking a sledgehammer to crack a nut. Any help would be great.
For a trivial case like this, I'd make them all static
and not worry about it too much. And definitely return an int
!
int getDiceRoll() {
static std::random_device rd;
static std::default_random_engine gen(rd());
static std::uniform_int_distribution<int> dis(1, 6);
return dis(gen);
}
You can wrap it all up in a class
like this:
#include <random>
#include <iostream>
/**
* (P)seudo (R)andom (N)umber (G)enerator
*/
template<typename Type = int>
class PRNG
{
// easier to use param_type
using param_type = typename std::uniform_int_distribution<Type>::param_type;
// store an instance of the generator/distribution in the class object
std::mt19937 gen;
std::uniform_int_distribution<Type> dis;
public:
// seed generator when creating
PRNG(): gen(std::random_device()()) {}
Type get(Type from, Type to)
{
// only need to create a light weigt param_type each time
return dis(gen, param_type{from, to});
}
};
int main()
{
PRNG<int> prng;
for(auto i = 0U; i < 10; ++i)
std::cout << "die roll " << i << ": " << prng.get(1, 6) << '\n';
}
Sample Output:
die roll 0: 2
die roll 1: 6
die roll 2: 1
die roll 3: 5
die roll 4: 6
die roll 5: 3
die roll 6: 3
die roll 7: 6
die roll 8: 3
die roll 9: 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With