Is it modern C++ to use srand to set random seed?
Asked Answered
P

3

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?

Passkey answered 21/1, 2013 at 15:17 Comment(1)
Also see Why are std::shuffle methods being deprecated in C++14?Cony
N
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);
Ninfaningal answered 21/1, 2013 at 15:19 Comment(12)
Can you provide a code example? I have trouble understanding what to do exactly.Passkey
@cls I included an example.Ninfaningal
Thanks. What should I set lo and hi to?Passkey
@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.Ninfaningal
What's a good choice for a seed in this case? I guess the time works, but do I need to #include <ctime> for that?Passkey
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.Ninfaningal
And it appears Visual Studio also uses a PRNG for random_device :(Ninfaningal
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.Passkey
@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.Ninfaningal
@cls: /dev/{u,}random. IIRC, on MAC OS, they are both the same.Titanomachy
Oh sorry, yeah. /dev. How the heck did I write /etc.Ninfaningal
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).Stockmon
T
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

Titanomachy answered 21/1, 2013 at 15:21 Comment(2)
How is the version of random_shuffle that takes a RandomFunc&& r different from shuffle?Orazio
@Dave it requires a function that when called as r(n) to return a random number in the interval [0, n).Ninfaningal
B
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...).

Bethsaida answered 29/5, 2013 at 6:0 Comment(2)
It's GPLed, that might be a problem.Nilotic
That's right, I haven't thaugth about that, as I am GPLed-like too ;-)Bethsaida

© 2022 - 2024 — McMap. All rights reserved.