Skip to main content
gamedev.net
🔒 Locked

random_shuffle algorithm question

Started by caekillius 5 replies 1.1k views
Original Post
caekillius
caekillius
While recently doing some programming with random numbers, I was wondering about the specifics of the random_shuffle algorithm, particularly what happens when it is repeated in a program and how it relates to seeding the random number generator. srand(time(0)); random_shuffle(vec1.begin(), vec1.end()); random_shuffle(vec2.begin(), vec2.end()); Why exactly does the algorithm not produce exactly the same shuffle (for the elements) of each vector even if the number generator is not seeded.
IvanMilles
IvanMilles
The thing about random_shuffle is that it doesn't guarantee that it calls out to rand() under the hood. It is only required to provide a uniform distributon. You don't say anything about which compiler you're using, but chances are that the one used seeds itself. What you can do is provide your own RNG that calls rand().

Here's what I do myself:

struct bmRandomForSTL{   int operator() (int range)   {       static bool seeded = false;       if (!seeded)	   {           srand(time(0));           seeded = true;       }       return rand() % range;   }};...and when using:bmRandomForSTL random;random_shuffle (myList.begin(), myList.end(), random);

Ramblings: http://ivan.rusted.se
IvanMilles
IvanMilles
...and of course, if you need a reproducible sequence, just remove the call to srand(). :)
Ramblings: http://ivan.rusted.se
ToohrVyk
ToohrVyk
Compare this situation to the following one:

srand(time(0));rand(); // This gives you one valuerand(); // This gives you another value, which may or may not be the same


To shuffle randomly, random_shuffle uses a random number generator to generate random numbers. Because of this, the sequence of random numbers used by the first random_shuffle is different from the one used by the second one, unless you re-seed random_shuffle's random number generator to the same value before each of the two calls.
caekillius
caekillius
Quote:
Original post by IvanMilles
...and of course, if you need a reproducible sequence, just remove the call to srand(). :)


For some reason (unbeknowest to myself) a different sequence is produced in two otherwise identical vectors. I use Dev-C++ (which uses minGW as a compiler).
caekillius
caekillius
Quote:
Original post by ToohrVyk
Compare this situation to the following one:

srand(time(0)); rand(); // This gives you one valuerand(); // This gives you another value, which may or may not be the same


To shuffle randomly, random_shuffle uses a random number generator to generate random numbers. Because of this, the sequence of random numbers used by the first random_shuffle is different from the one used by the second one, unless you re-seed random_shuffle's random number generator to the same value before each of the two calls.


That explains it a lot better, cheers ToohrVyk.

Zahlman
Zahlman
Quote:
Original post by ToohrVyk
unless you re-seed random_shuffle's random number generator to the same value before each of the two calls.


Just wanted to highlight the work-around. :)

Practical applications of "a pseudo-random but still reproducible number stream" are not ubiquitous, but they certainly exist. In games, the most common use that I know of is to store an RNG seed in a save file, in order to avoid storing lots of generated data.

However, with std::rand you don't have access to the RNG stream's "internal state", and consequently you can't run two such streams simultaneously, or "pause" one and "resume" it later. For some purposes this is inadequate; in these cases you'll want to look at the [boost] RNGs, or perhaps roll your own (don't invent the algorithm! Try looking at what your implementation's std::rand() does and adapting it into a class).

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.