This lesson will look at some practical applications of random number generation.

Applications: Generating random numbers

Now we can do wonders with this random number generation. Following are two instructions we should keep in mind:

srand(time(0));  // preferably the first line in the main
int x = rand();

Let’s look at some applications of random number generation.

Tossing a coin

When we toss a coin, it gives either a head or a tail. We can mimic this by generating a random 0 or 1. How can we accomplish that?

Generate a random number by calling the rand() function and take the modulus by 2. It will map every value to either 0 or 1.

Let’s write a one-line expression for generating a coin toss:

Press + to interact
int random_TOSS = rand()%2;
if(random_TOSS==0) // assume this to be tail
{
// Code for tail here..
}
else // if(random_TOSS==1)
{
// Code for head here..
}

Rolling a dice

In a dice roll, we need numbers from 1 to 6. The rand()%6 function will generate a random number between 0 to 5. We don’t need a zero, but we need 6, which is not there. We can add 1 to the generated number, which will result in mapping 0 to 1, 1 to 2, 2 to 3, 3 to 4, 4 to 5, and 5 to 6.

So we will write the following expression:

int random_no = rand()%6 + 1;

Generating an even number within a range

  1. As we know, even numbers are divisible by 2 (that is, they are multiples of 2). So we can write the following to generate even random numbers:

    int random_even = rand() * 2;
    // or 
    random_even = (rand() / 2) * 2;
    

    The first solution has a little problem: multiplying by 2 could result in an integer overflow.

    The second solution solves that problem in a way that if the generated number is even, rand()/2 * 2 will not affect it. However, suppose the generated number is odd. In that case, division by 2 will shrink it to an integer (e.g., 21/2 will yield 10 due to integer division), and multiplying by two will result in an even number (one lesser than the generated odd number).

  2. What if we want to generate an even random number between 1 to 200?

    Think for a while!

Question: Even random numbers

Question

How many even numbers appear between the 1–200 range?

Show Answer

Now note the following:

  • There exist 100 even numbers in the range of 1–200.

    • That’s why we take a mod (%) with 100.
  • Taking mod (%) with 100 will shrink the number between 0–99, i.e., rand()%100.

  • By adding 1 to it, we can move the range 0–99 to 1–100—rand()%100 + 1.

  • Now, multiplying by 2 will map 1 to 2, 2 to 4, 3 to 6, and so on, all the way up to mapping 100 to 200. So, here is the final expression:

    (rand()%100+1)*2;
    

What if we have odd random numbers between 1–200?

Generating a random odd number

There are multiple ways to write this:

  1. One possibility could be to write the even number generation code above and subtract 1 from it, that is,

    (rand()%100+1)*2 - 1;
    
  2. The second possibility is instead of using the above idea,

    • We just generate a random number between 0 to 99 (because there are 100 odd numbers starting from 1 till 199).
    • Now, we’ll multiply by 2, resulting in a mapping of 0 to 0, 1 to 2, 3 to 6, and so on till 99 to 198.
    • Now, just add 1 to it, resulting in 0 mapped to 1, 2 mapped to 3, 4 mapped to 5 and so on, all the way up to 198 mapped to 199.

    So, the code will be this:

    (rand()%100)*2 + 1;
    

A random number within a range

Let’s take a simple example first.

Generating a random number between -200–200

First, notice the following:

  • We have a total of 401 numbers between -200 to 200 (-200 … 0 … 200). That’s why we will take a mod with 401, that is, rand() % 401, resulting in a random number between the range 0 ... 400.

  • Next, we’ll subtract -200 so that 0 is mapped to -200 and 1 is mapped to -199, … and 200 is mapped to 0,… and 201 is mapped to 1 and so on and 400 will be mapped to 200.

    So here is the final expression:

    (rand()%401)-200;
    

We have shown the working of (rand()%401)-200 below in the slideshow. Take a look at it:

Random even numbers within a range

What if we have a random even range between -200–200?

First, we need to identify the even numbers between -200 to 200 (-200 … 0 … 200). There are 201 even numbers in this range. We will do the following:

(rand()%201  - 100) * 2;

Here, -100 is used for the negative even numbers.

Multiple of 5 (-500–200)

There are 20 multiples of 5 that exist in the range of 1 to 100. Here, we have the range -500 to 200, which means that we have a total of 140 multiples of 5—20x7=140—plus 0. Therefore, we have a total of 141 numbers.

We will take a mod with 141 here:

(rand()%141)*5-500

In the statement above, -500 is used for negative multiples of 5.


Task: We have a range (R1–R2) and multiple M. Can you write a general expression?

Press + to interact
#include <iostream>
using namespace std;
int main() {
// Write your general expression here and practice the above random code
}

Let’s move to generate a random prime number.

Random prime numbers

Now, we want to generate a random prime number for different ranges. As an end user, the program should prompt for the range. For example, if the user enters 100, it means generating a random prime number between the first hundred prime numbers.

We will need two helper functions to solve this problem.

Finding Nth prime

First, we will make the following function:

int findNthPrime(int N);

It should return the Nth prime number.

  • Inside the findNthPrime(), we’ll have a loop that increments one by one through a variable v. In each iteration, we’ll check the value v of the loop. If the value of v is a prime number, we’ll store it in nthPrime and increment in count++.

  • When the count is equal to N, our program will exit from the loop and return the nthPrime.

Press + to interact
int findNthPrime(int N)
{
int count = 0;
int nthPrime;
for(int v=2; count!= N; v++)
{
if(isPrime(v))
{
count++;
nthPrime = v;
}
}
return nthPrime;
}

Generating a prime in a range

  • Now, we will make another function, randomPrime(), in which we will pass a range as a parameter.

  • We will generate a random number within the provided range. If it is a prime number, we’ll immediately return it. Otherwise, we’ll keep generating new numbers.

  • As soon as the generated random number is a prime number, we’ll return the value.

Here’s the complete code:

Press + to interact
int randomPrime(int range)
{
int r=1;
do{
r = rand()%(range+1);
}
while(!isPrime(r)); // this will loop until we have found a prime number.
return r;
}

Two implementations of prime number generation

The input to the function should be N, i.e., we need to generate a random prime between the first NN prime numbers. For example, if N is 6, the generated number could be one of the numbers from {2,3,5,7,11,13}\{2,3,5,7,11,13\}.

Let’s discuss two solutions for this task:

Solution 1

We’ll do the following:

  1. We’ll find the Nth prime number. For example, in the above case, for N = 6, it will be 13.

  2. Now generate a random number mod (Nth prime + 1). For the example above, this means generating a random number between 0 to 13 (since we’re taking mod 14).

  3. If the generated number is a prime number, return that generated number. Otherwise, keep generating the next random number.

Here’s the implementation:

Press + to interact
int generatingRandomPrime1(int N)
{
int range = FindNthPrime(N); // This function will return Nth prime
return randomPrime(range); // This function will return random prime number
}
Solution 2

In this implementation, we’ll do the following:

  1. First generate a random number r between 1 to N.
  2. Generate the rth prime number and return that value.

Here’s the implementation:

Press + to interact
int GeneratingRandomPrime2(int N)
{
int r = rand()%N + 1; // Generate a random number between 1-N ==> r
return FindNthPrime(r) ; // Generate r'th prime number
}

Let’s write the complete code and see the output:

Press + to interact
#include <iostream>
#include <math.h>
#include<cstdlib>
#include<time.h>
using namespace std;
bool isPrime(int N)
{
int limit = sqrt(N);
if(N<2)
return false;
for(int d=2; d<=limit; d++)
{
if(N%d==0)
return false;
}
return true;
}
int randomPrime(int range)
{
int r=1;
do
{
r = rand()%(range+1);
}
while(!isPrime(r));
return r;
}
int findNthPrime(int N)
{
int count = 0;
int nthPrime;
for(int v=2; count<N; v++)
{
if(isPrime(v))
{
count++;
nthPrime = v;
}
}
return nthPrime;
}
// Solution 1
int generatingRandomPrime1(int N)
// here if N is 100 it means genrate a random prime till 100'th prime number
{
int range = findNthPrime(N);
return randomPrime(range);
}
// Solution 2
int generatingRandomPrime2(int N)
// here if N is 100 it means generate a random prime till 100'th prime number
{
int r = rand()%N + 1; // Generate a random number between 1-N ==> r
return findNthPrime(r) ; // Generate rth prime number
}
void printNPrimes(int N)
{
cout << "Primes = { ";
for(int n=1; n<=N; n++)
{
cout << findNthPrime(n)<<" ";
}
cout << "}";
}
int main()
{
int N = 10;
srand(time(0));
cout << "Generating a random number between ";
printNPrimes(N);
cout << "\n\nThrough Method 1: \n\n";
cout << generatingRandomPrime1(N)<<endl;
cout << generatingRandomPrime1(N)<<endl;
cout << generatingRandomPrime1(N)<<endl;
// Through Method GeneratingRandomPrime2
cout << "\n\nThrough Method 2: \n\n";
cout << generatingRandomPrime2(N)<<endl;
cout << generatingRandomPrime2(N)<<endl;
cout << generatingRandomPrime2(N)<<endl;
return 0;
}

Data generation based on probability distribution

Let’s say we would like to generate stochastic-drivenA process or system that is influenced by randomness or probability. data based on probabilities. For example, we have a,b,c, and d with the following probabilities:

a = 1/5 or 2/10 
b = 3/10
c = 1/10
d = 2/5 or 4/10

We would like to create a data stream based on these probabilities. How can we generate that data?

Let’s write a randomCharacters() function that generates random characters according to the probability.

Idea:

  • First, take the LCM (the least common multiple) of all the probabilities. For example, in the above case, 10 is the LCM. So, we will take that LCM as the modular range.

  • Now, define ranges based on the positive probability (compared to the common denominator that is the LCM; for example, 1/5 will scale up to 2/10, and 2/5 will scale up to 4/10).

  • Randomly generate a number mod (LCM) and, based on the numerator of each character’s probability, assign each integer to a specific character(depending on its numerator of probability), e.g., 0–1 will map to a, 2–4 will map to b, 5 maps to c, and 6–9 maps to d, making it 2/10, 3/10, 1/10, 4/10, respectively.

So, we have the following implementation:

Press + to interact
char randomCharacters()
{
int v = rand()%10;
if(v == 0 || v == 1)
return 'a'; //return a if probability is 0 or 1
else if(v ==2 || v == 3 || v == 4)
return 'b'; //return b if probability is 2,3 or 4
else if(v == 5)
return 'c'; //return c if probability is 5
else
return 'd'; // return d if probability is greater than 5
}

Let’s write down a complete code for generating the stream based on the probability distribution of data:

Press + to interact
#include <iostream>
#include <math.h>
#include<cstdlib>
#include<time.h>
using namespace std;
char randomCharacters( )
{
int v = rand()%10;
if(v == 0 || v == 1)
return 'a';
else if(v ==2 || v == 3 || v == 4)
return 'b';
else if(v == 5)
return 'c';
else
return 'd';
}
int main()
{
srand(time(0));
int N = 1000;
float aCount=0, bCount=0, cCount=0, dCount=0;
char ch;
cout << "Data Length: "<<N<<endl;
// cin>>N;
for(int i=1; i<=N; i++)
{
ch = randomCharacters();
if(ch=='a')aCount++;
if(ch=='b')bCount++;
if(ch=='c')cCount++;
if(ch=='d')dCount++;
cout << ch;
if(i%25==0) // after every 25 characters goto the new line
cout << endl;
}
aCount/=1000; bCount/=1000; cCount/=1000; dCount/=1000;
cout << "In Data Probabilities:\n"
<< "P('a') = "<<aCount<<endl
<< "P('b') = "<<bCount<<endl
<< "P('c') = "<<cCount<<endl
<< "P('d') = "<<dCount<<endl;
return 0;
}
  • In lines 28–32, we generate a random character based on which count gets incremented in aCount, bCount, cCount, and dCount.

  • In line 37, we convert the counts into probabilities by dividing the frequency with total cardinalitythe number of unique elements in any set of the data.

Exploration Task: Verify by executing the code above multiple times. Check whether the generated data is very close to the required probabilities of the characters in the data. Additionally, change different values of N to, for example, 10, 100, 1000, 10000, 100000. What happens when N gets bigger and bigger? Also, we recommend that you change the randomCharacters() function by changing the probabilities and even introducing new characters in the stream with different probabilities.

We will apply this random number generation concept later when we initialize the arrays with random data. For instance, we can initialize arrays with random even or odd numbers.

Summary

In this lesson, we learned several applications of the time(0) function, including measuring the time of the program and connecting it to random number generation. After learning how the rand() function works along with srand(time(0)), we made several expressions for generating random numbers, random primes, and random experimental stochastic data based on probability distribution.