[c++] How to generate a random number in C++?

I'm trying to make a game with dice, and I need to have random numbers in it (to simulate the sides of the die. I know how to make it between 1 and 6). Using

#include <cstdlib> 
#include <ctime> 
#include <iostream>

using namespace std;

int main() 
{ 
    srand((unsigned)time(0)); 
    int i;
    i = (rand()%6)+1; 
    cout << i << "\n"; 
}

doesn't work very well, because when I run the program a few times, here's the output I get:

6
1
1
1
1
1
2
2
2
2
5
2

So I want a command that will generate a different random number each time, not the same one 5 times in a row. Is there a command that will do this?

This question is related to c++ random

The answer is


#include <iostream>
#include <cstdlib>
#include <ctime>

int main() {
    srand(time(NULL));
    int random_number = std::rand(); // rand() return a number between ?0? and RAND_MAX
    std::cout << random_number;
    return 0;
}

http://en.cppreference.com/w/cpp/numeric/random/rand


Can get full Randomer class code for generating random numbers from here!

If you need random numbers in different parts of the project you can create a separate class Randomer to incapsulate all the random stuff inside it.

Something like that:

class Randomer {
    // random seed by default
    std::mt19937 gen_;
    std::uniform_int_distribution<size_t> dist_;

public:
    /*  ... some convenient ctors ... */ 

    Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
        : gen_{seed}, dist_{min, max} {
    }

    // if you want predictable numbers
    void SetSeed(unsigned int seed) {
        gen_.seed(seed);
    }

    size_t operator()() {
        return dist_(gen_);
    }
};

Such a class would be handy later on:

int main() {
    Randomer randomer{0, 10};
    std::cout << randomer() << "\n";
}

You can check this link as an example how i use such Randomer class to generate random strings. You can also use Randomer if you wish.


for random every RUN file

size_t randomGenerator(size_t min, size_t max) {
    std::mt19937 rng;
    rng.seed(std::random_device()());
    //rng.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);

    return dist(rng);
}

This code produces random numbers from n to m.

int random(int from, int to){
    return rand() % (to - from + 1) + from;
}

example:

int main(){
    srand(time(0));
    cout << random(0, 99) << "\n";
}

Here is a simple random generator with approx. equal probability of generating positive and negative values around 0:

  int getNextRandom(const size_t lim) 
  {
        int nextRand = rand() % lim;
        int nextSign = rand() % lim;
        if (nextSign < lim / 2)
            return -nextRand;
        return nextRand;
  }


   int main()
   {
        srand(time(NULL));
        int r = getNextRandom(100);
        cout << r << endl;
        return 0;
   }

I know how to generate random number in C++ without using any headers, compiler intrinsics or whatever.

#include <cstdio> // Just for printf
int main() {
    auto val = new char[0x10000];
    auto num = reinterpret_cast<unsigned long long>(val);
    delete[] val;
    num = num / 0x1000 % 10;
    printf("%llu\n", num);
}

I got the following stats after run for some period of time:

0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343

Looks random.

How it works:

  • Modern compilers protect you from buffer overflow using ASLR (address space layout randomization).
  • So you can generate some random numbers without using any libraries, but it is just for fun. Do not use ASLR like that.

Using modulo may introduce bias into the random numbers, depending on the random number generator. See this question for more info. Of course, it's perfectly possible to get repeating numbers in a random sequence.

Try some C++11 features for better distribution:

#include <random>
#include <iostream>

int main()
{
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]

    std::cout << dist6(rng) << std::endl;
}

See this question/answer for more info on C++11 random numbers. The above isn't the only way to do this, but is one way.


Whenever you do a basic web search for random number generation in the C++ programming language this question is usually the first to pop up! I want to throw my hat into the ring to hopefully better clarify the concept of pseudo-random number generation in C++ for future coders that will inevitably search this same question on the web!

The Basics

Pseudo-random number generation involves the process of utilizing a deterministic algorithm that produces a sequence of numbers whose properties approximately resemble random numbers. I say approximately resemble, because true randomness is a rather elusive mystery in mathematics and computer science. Hence, why the term pseudo-random is utilized to be more pedantically correct!

Before you can actually use a PRNG, i.e., pseudo-random number generator, you must provide the algorithm with an initial value often referred too as the seed. However, the seed must only be set once before using the algorithm itself!

/// Proper way!
seed( 1234 ) /// Seed set only once...
for( x in range( 0, 10) ):
  PRNG( seed ) /// Will work as expected

/// Wrong way!
for( x in rang( 0, 10 ) ):
  seed( 1234 ) /// Seed reset for ten iterations!
  PRNG( seed ) /// Output will be the same...

Thus, if you want a good sequence of numbers, then you must provide an ample seed to the PRNG!

The Old C Way

The backwards compatible standard library of C that C++ has, uses what is called a linear congruential generator found in the cstdlib header file! This PRNG functions through a discontinuous piecewise function that utilizes modular arithmetic, i.e., a quick algorithm that likes to use the modulo operator '%'. The following is common usage of this PRNG, with regards to the original question asked by @Predictability:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main( void )
{
  int low_dist  = 1;
  int high_dist = 6;
  std::srand( ( unsigned int )std::time( nullptr ) );
  for( int repetition = 0; repetition < 10; ++repetition )
    std::cout << low_dist + std::rand() % ( high_dist - low_dist ) << std::endl;
  return 0;
}

The common usage of C's PRNG houses a whole host of issues such as:

  1. The overall interface of std::rand() isn't very intuitive for the proper generation of pseudo-random numbers between a given range, e.g., producing numbers between [1, 6] the way @Predictability wanted.
  2. The common usage of std::rand() eliminates the possibility of a uniform distribution of pseudo-random numbers, because of the Pigeonhole Principle.
  3. The common way std::rand() gets seeded through std::srand( ( unsigned int )std::time( nullptr ) ) technically isn't correct, because time_t is considered to be a restricted type. Therefore, the conversion from time_t to unsigned int is not guaranteed!

For more detailed information about the overall issues of using C's PRNG, and how to possibly circumvent them, please refer to Using rand() (C/C++): Advice for the C standard library’s rand() function!

The Standard C++ Way

Since the ISO/IEC 14882:2011 standard was published, i.e., C++11, the random library has been apart of the C++ programming language for a while now. This library comes equipped with multiple PRNGs, and different distribution types such as: uniform distribution, normal distribution, binomial distribution, etc. The following source code example demonstrates a very basic usage of the random library, with regards to @Predictability's original question:

#include <iostream>
#include <cctype>
#include <random>

using u32    = uint_least32_t; 
using engine = std::mt19937;

int main( void )
{
  std::random_device os_seed;
  const u32 seed = os_seed();

  engine generator( seed );
  std::uniform_int_distribution< u32 > distribute( 1, 6 );

  for( int repetition = 0; repetition < 10; ++repetition )
    std::cout << distribute( generator ) << std::endl;
  return 0;
}

The 32-bit Mersenne Twister engine, with a uniform distribution of integer values was utilized in the above example. (The name of the engine in source code sounds weird, because its name comes from its period of 2^19937-1 ). The example also uses std::random_device to seed the engine, which obtains its value from the operating system (If you are using a Linux system, then std::random_device returns a value from /dev/urandom).

Take note, that you do not have to use std::random_device to seed any engine. You can use constants or even the chrono library! You also don't have to use the 32-bit version of the std::mt19937 engine, there are other options! For more information about the capabilities of the random library, please refer to cplusplus.com

All in all, C++ programmers should not use std::rand() anymore, not because its bad, but because the current standard provides better alternatives that are more straight forward and reliable. Hopefully, many of you find this helpful, especially those of you who recently web searched generating random numbers in c++!


If you are using boost libs you can obtain a random generator in this way:

#include <iostream>
#include <string>

// Used in randomization
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>

using namespace std;
using namespace boost;

int current_time_nanoseconds(){
    struct timespec tm;
    clock_gettime(CLOCK_REALTIME, &tm);
    return tm.tv_nsec;
}

int main (int argc, char* argv[]) {
    unsigned int dice_rolls = 12;
    random::mt19937 rng(current_time_nanoseconds());
    random::uniform_int_distribution<> six(1,6);

    for(unsigned int i=0; i<dice_rolls; i++){
        cout << six(rng) << endl;
    }
}

Where the function current_time_nanoseconds() gives the current time in nanoseconds which is used as a seed.


Here is a more general class to get random integers and dates in a range:

#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"


using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;


class Randomizer {
private:
    static const bool debug_mode = false;
    random::mt19937 rng_;

    // The private constructor so that the user can not directly instantiate
    Randomizer() {
        if(debug_mode==true){
            this->rng_ = random::mt19937();
        }else{
            this->rng_ = random::mt19937(current_time_nanoseconds());
        }
    };

    int current_time_nanoseconds(){
        struct timespec tm;
        clock_gettime(CLOCK_REALTIME, &tm);
        return tm.tv_nsec;
    }

    // C++ 03
    // ========
    // Dont forget to declare these two. You want to make sure they
    // are unacceptable otherwise you may accidentally get copies of
    // your singleton appearing.
    Randomizer(Randomizer const&);     // Don't Implement
    void operator=(Randomizer const&); // Don't implement

public:
    static Randomizer& get_instance(){
        // The only instance of the class is created at the first call get_instance ()
        // and will be destroyed only when the program exits
        static Randomizer instance;
        return instance;
    }
    bool method() { return true; };

    int rand(unsigned int floor, unsigned int ceil){
        random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
        return (rand_(rng_));
    }

    // Is not considering the millisecons
    time_duration rand_time_duration(){
        boost::posix_time::time_duration floor(0, 0, 0, 0);
        boost::posix_time::time_duration ceil(23, 59, 59, 0);
        unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
        return seconds(rand_seconds);
    }


    date rand_date_from_epoch_to_now(){
        date now = second_clock::local_time().date();
        return rand_date_from_epoch_to_ceil(now);
    }

    date rand_date_from_epoch_to_ceil(date ceil_date){
        date epoch = ptime(date(1970,1,1)).date();
        return rand_date_in_interval(epoch, ceil_date);
    }

    date rand_date_in_interval(date floor_date, date ceil_date){
        return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
    }

    ptime rand_ptime_from_epoch_to_now(){
        ptime now = second_clock::local_time();
        return rand_ptime_from_epoch_to_ceil(now);
    }

    ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
        ptime epoch = ptime(date(1970,1,1));
        return rand_ptime_in_interval(epoch, ceil_date);
    }

    ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
        time_duration const diff = ceil_date - floor_date;
        long long gap_seconds = diff.total_seconds();
        long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
        return floor_date + seconds(step_seconds);
    }
};

Generate a different random number each time, not the same one six times in a row.

Use case scenario

I likened Predictability's problem to a bag of six bits of paper, each with a value from 0 to 5 written on it. A piece of paper is drawn from the bag each time a new value is required. If the bag is empty, then the numbers are put back into the bag.

...from this, I can create an algorithm of sorts.

Algorithm

A bag is usually a Collection. I chose a bool[] (otherwise known as a boolean array, bit plane or bit map) to take the role of the bag.

The reason I chose a bool[] is because the index of each item is already the value of each piece of paper. If the papers required anything else written on them then I would have used a Dictionary<string, bool> in its place. The boolean value is used to keep track of whether the number has been drawn yet or not.

A counter called RemainingNumberCount is initialised to 5 that counts down as a random number is chosen. This saves us from having to count how many pieces of paper are left each time we wish to draw a new number.

To select the next random value I'm using a for..loop to scan through the bag of indexes, and a counter to count off when an index is false called NumberOfMoves.

NumberOfMoves is used to choose the next available number. NumberOfMoves is first set to be a random value between 0 and 5, because there are 0..5 available steps we can make through the bag. On the next iteration NumberOfMoves is set to be a random value between 0 and 4, because there are now 0..4 steps we can make through the bag. As the numbers are used, the available numbers reduce so we instead use rand() % (RemainingNumberCount + 1) to calculate the next value for NumberOfMoves.

When the NumberOfMoves counter reaches zero, the for..loop should as follows:

  1. Set the current Value to be the same as for..loop's index.
  2. Set all the numbers in the bag to false.
  3. Break from the for..loop.

Code

The code for the above solution is as follows:

(put the following three blocks into the main .cpp file one after the other)

#include "stdafx.h"
#include <ctime> 
#include <iostream>
#include <string>

class RandomBag {
public:
    int Value = -1;

    RandomBag() {
        ResetBag();

    }

    void NextValue() {
        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        int NumberOfMoves = rand() % (RemainingNumberCount + 1);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            if (BagOfNumbers[i] == 0) {
                NumberOfMoves--;

                if (NumberOfMoves == -1)
                {
                    Value = i;

                    BagOfNumbers[i] = 1;

                    break;

                }

            }



        if (RemainingNumberCount == 0) {
            RemainingNumberCount = 5;

            ResetBag();

        }
        else            
            RemainingNumberCount--; 

    }

    std::string ToString() {
        return std::to_string(Value);

    }

private:
    bool BagOfNumbers[6]; 

    int RemainingNumberCount;

    int NumberOfMoves;

    void ResetBag() {
        RemainingNumberCount = 5;

        NumberOfMoves = rand() % 6;

        int BagOfNumbersLength = sizeof(BagOfNumbers) / sizeof(*BagOfNumbers);

        for (int i = 0; i < BagOfNumbersLength; i++)            
            BagOfNumbers[i] = 0;

    }

};

A Console class

I create this Console class because it makes it easy to redirect output.

Below in the code...

Console::WriteLine("The next value is " + randomBag.ToString());

...can be replaced by...

std::cout << "The next value is " + randomBag.ToString() << std::endl; 

...and then this Console class can be deleted if desired.

class Console {
public:
    static void WriteLine(std::string s) {
        std::cout << s << std::endl;

    }

};

Main method

Example usage as follows:

int main() {
    srand((unsigned)time(0)); // Initialise random seed based on current time

    RandomBag randomBag;

    Console::WriteLine("First set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nSecond set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nThird set of six...\n");

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    randomBag.NextValue();

    Console::WriteLine("The next value is " + randomBag.ToString());

    Console::WriteLine("\nProcess complete.\n");

    system("pause");

}

Example output

When I ran the program, I got the following output:

First set of six...

The next value is 2
The next value is 3
The next value is 4
The next value is 5
The next value is 0
The next value is 1

Second set of six...

The next value is 3
The next value is 4
The next value is 2
The next value is 0
The next value is 1
The next value is 5

Third set of six...

The next value is 4
The next value is 5
The next value is 2
The next value is 0
The next value is 3
The next value is 1

Process complete.

Press any key to continue . . .

Closing statement

This program was written using Visual Studio 2017, and I chose to make it a Visual C++ Windows Console Application project using .Net 4.6.1.

I'm not doing anything particularly special here, so the code should work on earlier versions of Visual Studio too.


Here is a solution. Create a function that returns the random number and place it outside the main function to make it global. Hope this helps

#include <iostream>
#include <cstdlib>
#include <ctime>
int rollDie();
using std::cout;
int main (){
    srand((unsigned)time(0));
    int die1;
    int die2;
    for (int n=10; n>0; n--){
    die1 = rollDie();
    die2 = rollDie();
    cout << die1 << " + " << die2 << " = " << die1 + die2 << "\n";
}
system("pause");
return 0;
}
int rollDie(){
    return (rand()%6)+1;
}