Quick–choose a number between 1 and 10! What number did you choose?
Let’s say you chose the number 4.
#include <stdio.h>
int main(void)
{
int num = 0;
("Choose a number between 1 and 10: ");
printf
do
{
("%d", &num);
scanf} while (num < 1 || num > 10);
("You chose: %d.\n", num);
printf
return 0;
}
If we ran our code, we would see this:
Choose a number between 1 and 10: 4
You chose: 4.
Here, we take user input and store the value 4. However, let’s say we were debugging our code and didn’t want to keep entering random numbers by hand. Is there anything we could do to save ourselves the effort?
rand()
and srand()
.Thankfully, C supplies us with two functions in stdlib.h
to help us generate random numbers: rand()
and
srand()
.
First, we’ll look at rand()
. It can be used to return a
random integer between 0 and RAND_MAX
, a constant that will
be at least 32767. You can assign a variable its return value like
so:
#include <stdio.h>
#include <stdlib.h> // Don't forget to include this!
int main(void)
{
// num1 is assigned a value between 0 and RAND_MAX.
int num1 = rand();
("num1 = %d.\n", num1);
printf
return 0;
}
num1 = 41.
Pretty neat, huh?
If you want to find out what RAND_MAX
is on your system,
you can use the following code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
("On my system, RAND_MAX is %d.\n", RAND_MAX);
printf
return 0;
}
On my system, RAND_MAX is 32767.
Let’s go back to our opening example.
Remember that we can use the modulus operator, %
, to
return a number between 0 and n-1
, where n
is
the number we modulo by. Let’s perform rand()
modulo 10 to
return a number between 0 and 9.
// This modulo operation returns a number between 0 and 9.
int random_num = rand() % 10;
Now, we can add 1 to the result to bring the value to between 1 and 10.
// random_num is now between 1 and 10.
+= 1; random_num
As a whole, the concept looks like this:
// Generates a random number between 1 and 10.
int random_num = (rand() % 10) + 1;
Let’s take this concept a step further. Say you want to return a number between any two numbers. If we use the example above as a guide, we see that our upper bound was 10 and our lower bound was 1, giving us a range of 10 numbers. We can calculate that using this formula:
int range = (upper_bound - lower_bound) + 1;
If we plug 10 and 1 into their proper places, we see that
range
evaluates to 10.
int range = (10 - 1) + 1;
Now we use what we know to find a different range. I’ve been feeling pretty lucky today, so I want my lower bound to be 7. Maybe you’ve been feeling 100 percent on top of things lately, so we’ll make our upper bound 100.
int lower_bound = 7;
int upper_bound = 100;
Using the formula above, we see that range
evaluates to
94.
int range = (100 - 7) + 1;
Next, we modulo rand()
by range
to get
numbers between 0 and 93.
int another_random_num = rand() % range;
Finally, we add lower_bound
to the previous result to
have our numbers fall between 7 and 100.
+= lower_bound; another_random_num
If we hard-coded all of the values and put the expression on one line, it would look like this:
// (rand() % (upper_bound - lower_bound + 1)) + lower_bound
int another_random_num = (rand() % (100 - 7 + 1)) + 7
rand()
and srand()
: psuedo-random generators.I have a secret to tell you: the result of rand()
actually isn’t entirely random. Officially, rand()
and srand()
are known as “pseudo-random sequence generation
functions” . Simply put, that means the output from rand()
can be predicted if you know its input and underlying
algorithm. However, we don’t see it taking any input, so where
is the input coming from?
Behind the scenes, it is given a positive integer, or
unsigned int
, called a seed to operate on. When you start
your program, the seed has a default value of 1. If you use that seed
across different program runs, you will generate the same set of random
numbers each time.
rand()
:
the srand()
function.This is where srand()
comes into play. Once you pass
srand()
a seed, rand()
can use it to generate
random numbers.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Declaring and initializing a seed variable.
int your_seed = 4;
// Passing your_seed to srand().
(your_seed);
srand
// Calling rand() after seeding srand().
int last_random_num = rand();
("Your random number: %d.\n", last_random_num);
printf
return 0;
}
Running our code gives us this:
Your random number: 0.
rand()
and srand()
.That’s great, but as it currently stands, a little mysterious. How
exactly do the two work together? Well, if we were to peek inside of
stdlib.h
, we would see code that looked like this:
// In stdlib.h.
// seed is visible to both rand() and srand(). Its default value is 1.
unsigned int seed = 1;
// Note: This is not the actual algorithm, only a simplified example.
int rand(void)
{
= (seed * 5) + 1;
seed return (seed / 2) % 10;
}
void srand(unsigned int your_seed)
{
// Sets the global seed variable to the your_seed value passed into the function.
= your_seed;
seed }
When we ran our example from earlier in the section, the process to
get our 0
value worked like this.
// In the background...
// seed starts as 1.
unsigned int seed = 1;
void srand(unsigned int your_seed)
{
// Reassigns seed using your_seed.
= 4;
seed }
int rand(void)
{
// seed evaluates to 21, which is then stored in the global variable.
= (4 * 5) + 1;
seed
// Returns 0 to the main function.
return (21 / 2) % 10;
}
It is considered good practice to call srand()
only
once, at the start of your program. While useful for
predictability, you may not want to use the same seed every time. In
that case, pass time(NULL)
to srand()
to use
the current time as a seed–and don’t forget to include
<time.h>
!
#include <stdio.h>
#include <stdlib.h> // rand() and srand().
#include <time.h> // Accessing the time() function.
int main(void)
{
// Seeding srand() with the current time.
(time(NULL));
srand
// Calling rand() after seeding srand().
int last_random_num = rand();
("Your random number: %d.\n", last_random_num);
printf
return 0;
}