4

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.

3
  • It really depends on what you are doing. In this example I would have the random number generator be a member of the class. Commented Oct 29, 2015 at 17:28
  • You can't really imitate rand with good style, since rand is a design atrocity (for a library facility). But if it's a global PRNG that you need, then just make one. Commented Oct 29, 2015 at 17:49
  • 1
    What are your requirements concerning thread safety? Have you considered using dependency injection for easier unit testing and maintainability? Commented Oct 29, 2015 at 20:00

3 Answers 3

4

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); } 
Sign up to request clarification or add additional context in comments.

3 Comments

Why the downvote? Is there a compelling reason to have them be nonlocal?
It may also be worth making the static variables thread_local in a mt environment.
Okay, thanks for the variety of answers, they are clear and I get the picture. Anything else that confuses me about this is probably not appropriate for a specific question here, but more generally about building up skills in applying the right design principles in OO code at the right time etc.
3

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 

Comments

2

I didn't compile so there might be some syntax errors... but you get the idea, something like this.

class foo { public: foo() { e1 = std::default_random_engine(rd()); uniform_dist = std::uniform_int_distribution<int>(1, 6); } int getDiceRoll() { return uniform_dist(e1); } private: std::random_device rd; std::default_random_engine e1; std::uniform_int_distribution<int> uniform_dist; }; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.