user6300260
user6300260

Reputation:

rand() and srand() functions in c++

I have been learning recently how to program games in c++ from a beginner book, and i reached a lesson where i have to make a game in where i have to guess the computer's random picked number, and i have to use this line of code:

srand(static_cast<unsigned int>(time(0)));
variable=rand();

I obviously use iostream cstdlib and ctime.I don't really understand how this works.How is it picking the time and date, and by what rules is it converting into an unsigned int. Basically, how those functions work. Thank you!

Upvotes: 0

Views: 4040

Answers (2)

Baum mit Augen
Baum mit Augen

Reputation: 50063

1. About time()

time (or better std::time in C++) is a function that returns some integer or floating point number that represents the current time in some way.

Which arithmetic type it actually returns and how it represents the current time is unspecified, however, most commonly you will get some integer type that holds the seconds since begin of the Unix epoch.

2. About srand()

srand is a function that uses its argument (which is of type unsigned int), the so called seed, to set the internal state of the pseudo number generator rand. When I write random in the rest of this answer, read pseudo random.

Using a different seed will in general result in a different sequence of random numbers produced by subsequent calls to rand, while using the same seed again will result in the exactly same sequence of random numbers.

3. Using time() to seed rand()

If we do not want to get the same random numbers every time we run the program, we need some seed that is different on each run. The current time is a widely used source for such a seed as it changes constantly.

This integer (or whatever else time returned) representing the current time is now converted to unsigned int with a static_cast. This explicit cast is not actually needed as all arithmetic types convert to unsigned int implicitly, but the cast may silence some warnings. As time goes by, we can expect the resulting unsigned int and thus the sequence of random numbers produced by rand to change.

4. Pitfalls

If, as is common, time returns the number of seconds since the beginning of the Unix epoch, there are three important things to note:

  1. The sequence you produce will be different only if at least a second has passed between two invocations.
  2. Depending on the actual implementation, the resulting sequences may start of kind of similar if the time points used to seed rand are close to each other (compared to time since Epoch). Afaik, this is the case in MSVC's implementation. If that is problematic, just discard the first couple of hundred or thousand values of the sequence. (As I have learned by now, this does not really help much for poor RNGs as commonly used for rand. So if that is problematic, use <random> as described below.)
  3. Your numbers are not very random in the end: If someone knows when your call to srand occurred, they can derive the entire sequence of random numbers from that. This has actually led to a decryption tool for a ransom ware that used srand(time(0)) to generate its "random" encryption key.

Also, the sequence generated by rand tends to have poor statistical properties even if the seed was good. For a toy program like yours, that is probably fine, however, for real world use, one should be aware of that.

5. The new <random>

C++11 introduced new random number facilities that are in many ways superior to the old rand based stuff. They provided in the standard header <random>. It includes std::random_device which provides a way to get actually random seeds, powerful pseudo random number generators like std::mt19937 and facilities to map the resulting random sequences to integer or float ranges without introducing unnecessary bias.

Here is an example how to randomly roll a die in C++11:

#include <random>
#include <iostream>
 
int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 6);
 
    for (int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

(Code from cppr) Note: std::random_device does not work properly with MinGW, at least in the version (Nuwen MinGW5.3) I tested!

It should also be noted that the state space of a mt19937 is much larger than the 32 bit we (commonly) get out of a single call to random_device. Again, this will most likely not matter for toy programs and homework, but for reference: Here is my attempt to properly seed the entire state space, plus some helpful suggestions in the answers.

If you are interested in more details about rand vs <random>, this is an interesting watch.

Upvotes: 9

orbitcowboy
orbitcowboy

Reputation: 1538

First line: srand() is a pseudo-random number generator. In your case it is initialized with the current time (execution time) on your system. Second line: After the pseudo-random number generator is configured, you can retrieve random numbers by calling rand().

Upvotes: 0

Related Questions