15

For code that uses std::random_shuffle, I need to set a random seed so that the pseudorandom sequences produced vary in each program run.

The code example here makes a call to

srand ( unsigned ( time (NULL) ) );

which needs to

#include <ctime>
#include <cstdlib>

I wonder: Since C++11 includes major updates to pseudorandom number generation, is this still up to date? What should I use to set the random seed for std::random_shuffle?

clstaudt
  • 21,436
  • 45
  • 156
  • 239

3 Answers3

25

random_shuffle uses an implementation-defined random number generator unless you provide one. So, no, using srand is not necessarily correct.

Otherwise it uses the generator you provide. You can use rand if you want to be sure that is what gets used.

srand(seed);
std::random_shuffle(first, last, [](int n) { return rand() % n; });
// this is a biased generator
// see <http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx>

However, I recommend using the new <random> facilities instead of rand(). Example follows.

std::default_random_engine gen(seed);

std::shuffle(first, last, gen);
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • Can you provide a code example? I have trouble understanding what to do exactly. – clstaudt Jan 21 '13 at 15:21
  • @cls I included an example. – R. Martinho Fernandes Jan 21 '13 at 15:22
  • Thanks. What should I set `lo` and `hi` to? – clstaudt Jan 21 '13 at 15:27
  • 2
    @cls Sorry, I got that wrong. You don't need a distribution at all. std::shuffle deals with that. Just seed a generator and pass it along. – R. Martinho Fernandes Jan 21 '13 at 15:28
  • What's a good choice for a seed in this case? I guess the time works, but do I need to `#include ` for that? – clstaudt Jan 21 '13 at 15:31
  • The same thing you would use to seed rand(), I guess. If your implementation supports it, you can use `std::random_device()()` (the two sets of parens are for constructing a temporary object and then calling op() on it to get a seed), which should use something like /etc/random or /etc/urandom on POSIX systems, or... not sure what on Windows. IIRC MinGW uses a PRNG for random_device, which isn't great. I hope it gets fixed in the future, but for now you should be aware of that and probably will prefer the time or some platform specific code. – R. Martinho Fernandes Jan 21 '13 at 15:33
  • And it appears Visual Studio also uses a PRNG for random_device :( – R. Martinho Fernandes Jan 21 '13 at 15:44
  • This works, thanks. I simply need the shuffled sequence to be different in each invocation, no cryptography involved. Just out of curiosity: Does `std::random_device` assume that there is a hardware nondeterministic random device? /etc/(u)random does not exist in my OSX 10.8, for example. Program still runs. – clstaudt Jan 21 '13 at 15:47
  • @cls it is allowed to use a PRNG if no suitable device exists (or if the implementers are too lazy to use it :P). You can test for this with the `random_device::entropy` function. If it returns nonzero, it uses a PRNG. – R. Martinho Fernandes Jan 21 '13 at 15:48
  • @cls: `/dev/{u,}random`. IIRC, on MAC OS, they are both the same. – rici Jan 21 '13 at 15:53
  • Oh sorry, yeah. /dev. How the heck did I write /etc. – R. Martinho Fernandes Jan 21 '13 at 15:57
  • 3
    Or, if you don't have any special requirements on the distribution and quality of the random numbers, you might be even better off with `std::default_random_engine` instead of `std::mt19937`, not messing with the implementation of the PRNG itself (in the end only somebody who understands how an MT behaves and why he needs one cares about that it actually is an MT). – Christian Rau Jan 21 '13 at 17:08
3

If you are using C++11, think about using std::shuffle instead of std::random_shuffle, and passing a random-number generator, as in the last example here

rici
  • 234,347
  • 28
  • 237
  • 341
0

If you really care about accuracy, quality and diversity of the ways to generate random numbers, I would highly suggest to consider using the famous Gnu Scientific Library (GSL)

This allows real uniform generation and various algorithms for the best. See here.

Specially this and this describes the available algorithms :

— gsl_rng_mt19937
— gsl_rng_taus
— gsl_rng_taus2
— gsl_rng_gfsr4
...

EDIT : Also boost::random should be a good alternative considering the GPLness of GSL (but I never dealed with it...).

Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85