Random number generator in C++11 without repetition

By , last updated October 12, 2019

Can’t find the right way to get a random number in the range of your choice?

If you are programming in C++ for a while, chances are you once got in a situation where you want to get some random number between two given ranges; you might have used old C-function rand() with an initial seed of NULL time, such as the following:

#include <stdlib.h>
#include <iostream>

int main()
{
    // initialize random seed
    srand(time(NULL));
    
    // random number between 1 and 10
    int n = rand() % 10 + 1;
    
    std::cout << "Random Number: " << n << std::endl;
}

Here, rand() plays a role of random number generator (RNG). A random number generator is simply an object that produces a sequence of pseudo-random values. Note that we must reset the “seed” with an initial value of time when the program is started, else it won’t give random values.

This is quite a common way to get a random number in C. However, the problem that you may have faced with it is that you get the same number several times in your program; that is, it doesn’t distribute numbers properly. That isn’t something you want to do.

In C++, <random> header provides many functions and templates which provide better distribution. With the advent of C++11, it got even more useful functions and random number generators. Following is its usage:

int main()
{
    std::random_device rd;   // non-deterministic generator
    std::mt19937 gen(rd());  // to seed mersenne twister.
    std::uniform_int_distribution<> dist(1,10); // distribute results between 1 and 10 inclusive.

    for (int i = 0; i < 9; ++i) {
        std::cout << dist(gen) << " "; // pass the generator to the distribution.
    }
    std::cout << std::endl;
}

You will now get better distribution. However, it can still give you same number, so this approach can be suitable for programs where it doesn’t matter such as lotteries, etc.

Getting the different number every time

Suppose, you are creating a vocabulary builder program, and you want to ask random questions from a player. Now, the program isn’t supposed to ask the same question again from the player when he/she answers a question, but rather it should ask different question every time a player answers one question.

In my previous article, I have told you different ways of finding an element in a container. We will use the approach where two containers (we will use std::vector) will be used: one for storing numbers and other for storing the previous numbers given by our random generator. Following is its implementation:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<unsigned int> a;
    std::vector<unsigned int>::iterator it;
    // Our Random Generator
    std::mt19937 eng{std::random_device{}()};

    for (int i=0;i<10;i++) {
        unsigned int q = std::uniform_int_distribution<unsigned int>{0, 10}(eng);

        do {
            q = std::uniform_int_distribution<unsigned int>{0, 10}(eng);
            it = std::find(a.begin(), a.end(), q);
        } while (it != a.end());

        a.push_back(q);

        std::cout << q << std::endl;
    }
}

Here, we are asking for different number from our RNG until the number isn’t present in our container of previous numbers. Now, it will give different number that isn’t given before by random generator in our given range. Here, std::mt19937 is a RNG called Mersenne Twister 19937. There are some other RNGs as well such as std::minstd_rand, std::mt19937_64, etc. You can use this approach whenever you need to get a random number that is different from the previous numbers.

Did this article help you in making your programming life easier?