6

In a function, I want to generate a list of numbers in range: (This function will be called only once when executing the program.)

void DataSet::finalize(double trainPercent, bool genValidData)
{
    srand(time(0));
    printf("%d\n", rand());

    // indices = {0, 1, 2, 3, 4, ..., m_train.size()-1}
    vector<size_t> indices(m_train.size());
    for (size_t i = 0; i < indices.size(); i++)
        indices[i] = i;

    random_shuffle(indices.begin(), indices.end());
// Output
    for (size_t i = 0; i < 10; i++)
        printf("%ld ", indices[i]);
    puts("");

}

The results are like:

850577673
246 239 7 102 41 201 288 23 1 237 

After a few seconds:

856981140
246 239 7 102 41 201 288 23 1 237 

And more:

857552578
246 239 7 102 41 201 288 23 1 237

Why the function rand() works properly but `random_shuffle' does not?

Dawei Yang
  • 606
  • 1
  • 9
  • 19
  • possible duplicate of [How to make sure that std::random\_shuffle always produces a different result?](http://stackoverflow.com/questions/6931951/how-to-make-sure-that-stdrandom-shuffle-always-produces-a-different-result) – Jonathon Reinhart Mar 19 '14 at 05:26
  • You should only call `srand()` once, at the beginning of your program. Also, see [this](http://stackoverflow.com/questions/6926433/how-to-shuffle-a-stdvector-in-c), and [this](http://stackoverflow.com/questions/13459953/random-shuffle-not-really-random) – Jonathon Reinhart Mar 19 '14 at 05:27
  • @JonathonReinhart, not a duplicate because he called `srand` once. Right? – Paul Draper Mar 19 '14 at 05:28
  • @PaulDraper Once *every time* he ran it. Also, there's lots of other advice on that question and the others I've linked. I can only mark one duplicate. – Jonathon Reinhart Mar 19 '14 at 05:29
  • @JonathonReinhart Thanks. I've read the advice. But I cannot figure out why `rand()` works and `random_shuffle()` doesn't seem to have any associations with `srand()`. – Dawei Yang Mar 19 '14 at 05:36
  • I move `srand()` call into `main` function, but the results are similar. – Dawei Yang Mar 19 '14 at 05:38
  • 1
    Can you see the example in here: http://www.cplusplus.com/reference/algorithm/random_shuffle/ I tried it and it gives me a different vector each time. And it uses `srand()`. – yasouser Mar 19 '14 at 05:40
  • @yasouser Yes, it works. The lambda-expr version: `random_shuffle(begin(indices), end(indices), [](int n) { return rand() % n; });` produces different result, but if I change my random generator to default_random_engine(), then the problems come. So the question becomes that why `default_random_engine()` not works. – Dawei Yang Mar 19 '14 at 05:45
  • @YangDawei: I modified the sample I cited to print the vector after the call to random_shuffle() with built-in random number generator. It also prints different vector each time. I'm using MinGW g++ v4.8.1 to compile the code on a Windows machine. – yasouser Mar 19 '14 at 05:59

1 Answers1

6

random_shuffle() isn't actually specified to use rand() and so srand() may not have any impact. If you want to be sure, you should use one of the C++11 forms, random_shuffle(b, e, RNG) or shuffle(b, e, uRNG).

An alternative would be to use random_shuffle(indices.begin(), indices.end(), rand()); because apparently your implementation of random_shuffle() is not using rand().

Halfdane
  • 100
  • 1
  • 7
  • 5
    Yes, I force the random_shuffle to use `rand()` so that it works properly. Instead of `random_shuffle(indices.begin(), indices.end(), rand())`, I use `random_shuffle(begin(indices), end(indices), [](int n) { return rand() % n; })` because the previous one produce errors. I use cmake installed by macports, with CXX flags -std=c++11. My g++ is clang-500.2.79, but I don't know what compiler is used exactly by cmake. – Dawei Yang Mar 19 '14 at 06:40
  • @YangDawei: you can, for example, `message("${CMAKE_CXX_COMPILER}")` in your `CMakeLists.txt` to find out which compiler is used. – lisyarus Mar 19 '14 at 09:13