Looping srand(time(NULL));

Hey, I noticed that when you loop a random number without a pause, it will output the same number like 20 times after eachother before changing the number. Example

5
5
5
5
5
5
5
5
2
2
2
2
2

Its not that I really need a work around for it, but I was wondering if there is any.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */


using namespace std;

int main(){
	

	
	while(true){
	int roll;
	srand (time(NULL));
	roll = rand() % 6 + 1;
	cout << "Number is "<< roll<<endl;
        }
return 0;}
Last edited on
Move the statement in Line 15 outside the loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */


using namespace std;

int main(){
	
	srand (time(NULL));
	
	while(true){
	int roll;
	roll = rand() % 6 + 1;
	cout << "Number is "<< roll<<endl;
        }
return 0;}
Last edited on
Ah nice, thanks alot! :D
The speed at which you are calling srand() is the issue. If you really want to seed on each call the seed needs to change for each iteration:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
  for(unsigned int idx = 0; idx < 10; ++idx)
  {
    LARGE_INTEGER ticks;
    QueryPerformanceCounter(&ticks); // win32 high performance timer
    srand(ticks.QuadPart);
    std::cout << (rand() % 6 + 1) << std::endl;
  }
  return 0;
}
Just checking...

But you do get the fact that the sequence of numbers isn't actually random -- it's pretend (pseudo) random from a given starting point -- so if you set the same seed you will then get exactly the same sequence of random number for the following successive calls to rand (code below.)

0). seq for seed(123) = 41 54 76 5 64 66 50 79

1). seq for seed(123) = 41 54 76 5 64 66 50 79 - same as result set 0

2). seq for seed(123) = 41 54 76 5 64 66 50 79 - same as result set 0

3). seq for seed(42) = 76 1 70 57 84 80 17 45

4). seq for seed(180) = 27 21 26 58 71 81 51 65

5). seq for seed(180) = 27 21 26 58 71 81 51 65 - same as result set 4

6). seq for seed(42) = 76 1 70 57 84 80 17 45 - same as result set 3

7). seq for seed(123) = 41 54 76 5 64 66 50 79 - same as result set 0


The other part of the equation is that time() has a precision of seconds. So it will return the same value for up to a second (depending on when you make the first call.)

Texan's suggestion to call srand() with the value returned by (e.g.) the WinAPI QueryPerformanceCounter() function would work but is unnecessary work for the computer. I don't think would make the "random" numbers any more random. (If you're using a C++11 compliant compiler you could use one of the new mechanisms for number generation, but they are more involved to use.
http://www.cplusplus.com/reference/random/ )

Moving srand() out of the loop, as bazetwo suggested, is the right solution (as a general rule you call srand() once at program startup.)

Andy

PS Turning it around, the fact that random numbers restart can be useful for testing purposes as you know the sequence will repeat. So when I use rand() in test code, I log the seed so I can feed it in if I need to repro a crash, for example. Sometimes the crash only occurs for just the right value!

Code for output above:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdlib>
using namespace std;

class Tester {
private:
    vector<vector<int>> old_results;
public:
    void test(int seed, int seq_len);
};

void Tester::test(int seed, int seq_len) {
    // re-seed
    srand(seed);
    // output new sequence
    vector<int> results;
    cout << old_results.size() << "). seq for seed(" << seed << ") =";
    for(int i = 0; i < seq_len; ++i) {
        int val = (rand() % 100 + 1);
        results.push_back(val); // remembering the values
        cout << " " << val;
    }
    // check results against previous runs
    auto iter = find(old_results.cbegin(), old_results.cend(), results);
    if(iter != old_results.cend()) { // if we find matching results, report the fact
        cout << " - same as result set " << distance(old_results.cbegin(), iter);
    }
    cout << "\n\n";
    // remember latest results
    old_results.push_back(results);
}

int main() {
    const int seeds[] = {123, 123, 123, 42, 180, 180, 42, 123};
    const int num_seeds = sizeof(seeds)/sizeof(seeds[0]);

    const int seq_len = 8;

    Tester tester;

    for(int i = 0; i < num_seeds; ++i) {
        tester.test(seeds[i], seq_len);
    }

    return 0;
}

Last edited on
Wauw, that looks awesome ;P So with that code the only limit is the speed of your OS and it change the number with every tick? Thanks :D

Last edited on
Topic archived. No new replies allowed.