Reputation: 85
I am begginer at C++ and would like to clarify something. I have a vector of strings and must shuffle it randomly.
I am trying to understand what are the differences between
std::random_shuffle(vector.begin(), vector.end());
int myrandom(int i) {
return std::rand() % i;
}
std::random_shuffle(cards_vector.begin(), cards_vector.end(), myrandom);
Both seem to work fine as long as I call the following function at the beggining of my main.c
srand(time(NULL));
I have also found another solution on the internet which uses std::default_random_engine
auto rng = std::default_random_engine{};
std::shuffle(cards_vector.begin(), cards_vector.end(), rng);
However, the solution above always return the same shuffle, even when the random seed is called in main. I am not sure whether that is intended or not.
I appreciate if someone could clarify this to me.
Upvotes: 0
Views: 546
Reputation: 9715
The function std::random_shuffle has two overloads. In short, that means you can call the same function with a different number of parameters.
std::random_shuffle(vector.begin(), vector.end());
calls an internal random generator which is defined by the implementation (compiler, operative system, standard libraries, ...). However, often it is internally used std::rand
.From the documentation:
The random number generator is implementation-defined, but the function std::rand is often used.
std::random_shuffle(cards_vector.begin(), cards_vector.end(), myrandom);
uses an explicit random generator (that you define; that is, myrandom
) which internally calls std::rand
.The function std::rand (from C) generate a pseudo-random number. It means that once you have set the seed it will generate (every time) the same number sequence. In other words, the sequence is deterministic depending on the initial value (called seed).
In order to set the seed (the initial value) for the std::rand
you need to call the function std::srand
which accepts the seed as argument.
The statement srand(time(NULL));
is an old common trick to initialize the generator with a "random" (not actually) seed. Indeed, the function time(NULL)
returns the current time which is supposed to be different every time is called.
Therefore, every time your program starts you set the seed with a different number and the generator std::rand
will produce a difference sequence every time.
Please Note That: std::random_shuffle
is an old C++ function and it has been deprecated. You should indeed use its replacement, that is, std::shuffle
.
However, the solution above always return the same shuffle, even when the random seed is called in main. I am not sure whether that is intended or not.
The rationale behind this is the same as above.
In that example you are using another (different from std::rand
) pseudo-random number generator, that is std::default_random_engine{}
. This generator is defaulted initialized with a default seed.
If you want to generate different results for different application run, you need to initialize the generator with a seed which is meant to be different every time your application starts.
A more correct code would be:
#include <algorithm>
#include <chrono>
#include <random>
// ...
auto rng = std::default_random_engine{std::chrono::system_clock::now().time_since_epoch().count()};
Upvotes: 2