C++ rand() always giving same TWO values... and then working perfectly

Viewed 417

First, I know the basic principle of planting a time seed, and my program's outputs are partially random. But this baffles me.

On subsequent executions of the program, the seven randomly generated values may look like this:

14 14 47 70 84 2 24

14 28 42 52 31 10 12

63 25 4 50 20 27 56

63 19 55 44 65 60 52

14 16 17 40 54 77 4

63 6 79 36 51 85 39

The rest of the values appear random, but the first value is always either 14 or 63. Why is this happening, and how can I make it completely random?

The code is supposed to draw a random Scrabble letter without replacement, with a cout statement added for debugging purposes.

#include <iostream>
using namespace std;

int main()
{
    string bag = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ";

    srand(time(0));
    for (int a = 0; a < 7; a++)
    {
        int i = rand()%bag.size();
        cout << i << ' ';
        bag.erase(i,1);
    }
    cout << endl;
    return 0;
}
  • Compiled in MacOS Catalina 10.15 terminal
  • Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
  • Apple clang version 11.0.0 (clang-1100.0.33.17)
  • Target: x86_64-apple-darwin19.6.0
  • Thread model: posix
1 Answers

rand() or std::rand() never generates true random number. It generates pseudo-random numbers. This is because computers are unable to generate truly random numbers itself, it requires assistance. Let's say you pressed a key exactly 2.054 seconds after the previous keypress. This is truly a random number. Computers use this data to generate truly random numbers. rand() or std::rand() generates a pseudo-random number, so needs to be seeded (with srand() or std::srand()). If the number you used to seed isn't random, the output wouldn't be random too. Moreover, you are using time() (or std::time()) which returns an int holding the number of seconds passed since epoch. So if you execute the program multiple times too rapidly, the seed would be the same and the output too. It also seems that your standard library a bad rand() or std::rand() function.

Example:

Output of the program (compiled from your code) executed 10 times rapidly (environment: Ubuntu, bash):

$ for i in {0..9} ; do ./a.out ; done
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42 
50 11 3 60 36 17 42

What to do?

I can suggest you use another time function to seed, which outputs time in milliseconds (or even nanoseconds) or get your own random number generator. See this article to know how pseudo-random number generators work. This will also help you to build your own as it seems that your standard library gives a bad rand() or std::rand() function.

Related