Reputation: 31
The following call for random shuffle is always giving the same results for the vector v
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::srand(time(0));
std::random_shuffle(v.begin(), v.end());
for (int i = 0; i < v.size(); ++i) {
printf("%d ", v[i]); printf("\n");
}
printf("%d\n", std::rand() % 100);
}
I've tried compiling using
g++ -std=c++0x
g++ -std=c++11
But both give the same results every time so I don't really understand what's going on.
$./a.out
7 1 4 6 8 9 5 2 3 10
26
$ ./a.out
7 1 4 6 8 9 5 2 3 10
41
$ ./a.out
7 1 4 6 8 9 5 2 3 10
39
Upvotes: 2
Views: 1518
Reputation: 1130
Modern C++
It is not guarenteed in the standard that std::random_shuffle
will relly on std::srand
.
--
Footnote: std::random_shuffle
is deprecated in C++14 and removed in C++17.
Since C++11 (the question is tagged with c++11
), it is better to use std::shuffle
and since C++20 to use std::ranges::shuffle
, with an explicit randomness generator. Example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::random_device rd;
std::mt19937 gen(rd()); // Mersenne Twister generator.
// std::shuffle(v.begin(), v.end(), gen);
std::ranges::shuffle(v, gen); // (Since C++20)
for (const auto& i : v) {
std::cout << i << std::endl;
}
}
Upvotes: 0
Reputation: 137315
OP's comment makes it clear that this is Clang and libc++ that they are using, not GCC/libstdc++.
A quick look at libc++'s random_shuffle
implementation shows that it uses an object of type __rs_default
as its source of randomness, and inspecting the implementation of __rs_default
shows that it simply uses a default-constructed std::mt19937
object:
__rs_default::result_type
__rs_default::operator()()
{
static mt19937 __rs_g;
return __rs_g();
}
In other words, in this implementation srand
has no effect whatsoever on the source of "randomness" used by the two-parameter version of random_shuffle
. (Scary quotes because it always uses a fixed seed.) Note that random_shuffle
is not required to use rand
at all, so you can't expect srand
to "work" in portable code anyway.
Use std::shuffle
and the <random>
facilities instead.
Upvotes: 8
Reputation: 171293
Firstly, -std=c++0x
and -std=c++11
mean exactly the same thing, so testing both is pointless.
You didn't provide a complete program (please read https://stackoverflow.com/help/mcve next time) so I guessed at the rest of your code, and I tried this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
srand(time(0));
random_shuffle(v.begin(), v.end());
for (int i : v)
std::cout << i << ' ';
std::cout << std::endl;
}
I get different results every second:
tmp$ ./a.out
2 1 8 5 9 7 6 3 10 4
tmp$ ./a.out
10 7 6 3 1 8 9 4 5 2
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1
tmp$ ./a.out
2 1 3 7 5 8 9 6 4 10
The times when it produces the same result are because the number of seconds returned by time(0)
is the same, and so the seed for the rand()
function is the same, and so the results are the same. If you wait a second so that time(0)
returns a different value you should get a different random shuffle of the elements.
If the code you are running is not the same as mine you might get different results, but we can't possibly explain the results because you didn't show us your code.
Upvotes: 4