Lukas Petrikas
Lukas Petrikas

Reputation: 85

clarification regarding std::random_shuffle to shuffle the vector

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

Answers (1)

BiagioF
BiagioF

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.

  • The version 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.

  • The version 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

Related Questions