Sometimes we want our program to obtain numbers at random, for example, to simulate a roll of the dice or the distribution of cards in a game. In Linux C we have several functions that allow us to obtain these random values.
In this explanation, we are going to see the basic use of these functions. Some of the things we discuss here are not useful for more serious applications, where the sequence of random numbers is required to be very random, unpredictable, not to repeat until after many numbers, etc, etc. However, the explanations presented here will work for most of our programs.
THE rand () FUNCTION:
In C, to get random numbers, we have the rand () function. This function, every time we call it, returns a random integer between 0 and the RAND_MAX (a huge number, like 2 billion).
The first problem that arises is that we do not usually want a random number in that range, it would be a very curious dice if it has so many faces. We may want, for example, a random number between 0 and 10. Or more generally, between 0 and N. The account that we must take for that is this:
number = rand ()% 11;
number = rand ()% (N + 1);
The modulo ( % ) operation gives us the remainder of dividing rand () by 11 . This remainder can range from 0 to 10 . Likewise, the module rand () between N + 1 ranges from 0 to N .
What if we want a range that does not start at 0? For example, we want a range between 20 and 30 (more generally, between M and N with N greater than M ). Well, it's easy, we get a number between 0 and 10 and add 20 to it (a number between 0 and N- M and add M )
number = rand ()% 11 + 20; // This is between 20 and 30
number = rand ()% (N-M + 1) + M; // This is between M and N
THE srand () FUNCTION:
We are presented with a new problem. If we run our program several times, the sequence of random numbers is repeated. Let's imagine we have a program that writes 3 random numbers between 0 and 10. We run it once and it comes out, for example, 4, 7 and 9. We run it a second time and it comes out again 4, 7 and 9. The third time it comes out the same and when we have had enough of running, the same thing comes out again.
The problem is that rand () "calculates" the random numbers. He starts from an initial number (called a seed), takes a few beads, and draws a random number. For the second number, take a few beads with the previous result and take a second number and so on.
If we rerun the program from the beginning, the starting number (the seed) used by rand () is the same, so the sequence of random numbers is the same since the counts are the same.
To avoid this problem we have the srand () function, to which a number is passed as a parameter that will be used as the initial number for the accounts. We only have to call this function once in our program.
What number do we put on this srand ()? We can't put a fixed number on it, because then we haven't done anything. We cannot put a number obtained with rand (), because the first time it will always give us the same and the result will be the same as if we put a fixed number. We must find a way to obtain a number that is different in the execution of each program.
There are two numbers that are commonly used for this:
- The system date/time. This value changes if we execute the program at a different point in time. We would have to start the program twice in the same second to obtain the same sequence of random numbers. In Linux C this date / time is obtained with the time () function
srand (time (NULL));
- The process number of the program. The first program that is started when the computer is started with the Linux operating system, has the process number 1, the second has 2, the third 3 and so on. When we start our program, it will be assigned the number that touches it, for example, 215. When we restart it, it will be assigned the one that touches it (it can be 216 if we have not executed anything in between or 345, if we have to entertain with other things). After running our program several thousand times, the process number may be repeated, but we will no longer remember the sequence that was taken the first time. The process number is obtained with getpid ()
srand (getpid ());
This function only has to be called once at the beginning of our program. Every time we call it, we will be restarting the random number calculations from the beginning, which will repeat everything.
THE drand48 () and srand48 () FUNCTIONS:
What if we want a random number with decimals? We function drand48 () which returns a random decimal number between 0.0 (included, can get the 0.0 ) and 1.0 (excluding, never leave 1.0 ). From there it is easy to transform it into the range we want. If we want a range between 10.0 and 20.0 (or between M and N where N is greater than M and both with decimals, even if they are .0)
number = drand48 () * (20.0-10.0) + 10.0;
number = drand48 () * (NM) + N;
In the same way as before, the sequence of random numbers will be repeated every time we execute our program and in the same way, we have a way to change the "seed" of that sequence. You have to call the srand48 () function, passing it an integer that is different in each execution of the program. Again, we have the two previous options
srand48 (time (NULL));
srand48 (getpid ());