1

The following call for random shuffle is always giving the same results for the vector v

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>

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 = 0; i < v.size(); ++i) printf("%d ", v[i]); printf("\n");
  printf("%d\n", rand() % 100);

  return 0;
}

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
  • 1
    Where/when do you call `srand(time(0));`? How are you testing? – Mooing Duck Oct 04 '16 at 21:06
  • May be relevent http://stackoverflow.com/questions/4926622/how-to-generate-different-random-numbers-in-a-loop-in-c – Fantastic Mr Fox Oct 04 '16 at 21:07
  • Welcome to stackoverflow, please provide a **complete** program when asking "why doesn't this code work?" so we don't have to waste our time adding the missing code that you already have sitting in front of you. – Jonathan Wakely Oct 04 '16 at 21:07
  • Why aren't you using [`std::shuffle`](http://en.cppreference.com/w/cpp/algorithm/random_shuffle) – Ryan Haining Oct 04 '16 at 21:08
  • 1
    @AnaEchavarria it always generates different result for me. However it must always generate the same result if launched within the same second. – fukanchik Oct 04 '16 at 21:10
  • What's your GCC version? – T.C. Oct 04 '16 at 21:43
  • Hi, sorry for not including the entire code. I have done that now. I still get the same result when running more than one second apart. I'm not sure if this is a problem with my compiler or how I can fix it and I would appreciate your help since I can't find my answer in the other forums. `$ g++ --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 7.0.2 (clang-700.1.81) Target: x86_64-apple-darwin15.6.0 Thread model: posix` – Ana Echavarria Oct 04 '16 at 21:45
  • 1
    This is clang/libc++. Their `random_shuffle` doesn't use `rand` as the source of randomness. – T.C. Oct 04 '16 at 21:49
  • Don't use the two parameter version of `random_shuffle`. The source of randomness is implementation defined. – David Schwartz Oct 04 '16 at 21:58

2 Answers2

6

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.

Community
  • 1
  • 1
T.C.
  • 133,968
  • 17
  • 288
  • 421
  • If `` should be forbidden for some reason (teacher or the like), you can hack your way around this by calling `std::random_shuffle` `time()` (maybe mod smth. if it takes to long, didn't test that) times. That's really a hack though, use the `` stuff if possible, as TC said. – Baum mit Augen Oct 04 '16 at 22:21
4

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.

Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Thank you Jonathan. I have updated the question to include the entire code. I wait more than one second to rerun it but still get the same result. I know the `srand(time(0))` is working because if I add a like to print the value of `rand()` it produces a different result every time. It is just the `random_shuffle` that is producing the same results. – Ana Echavarria Oct 04 '16 at 21:34