Chapter 6: Random Number Generation

Introduction

Random number generation is a crucial part of many applications, from simulations to games. In this chapter, we will explore different random number generators (RNGs) in C++, their usage, and best practices for seeding and generating random numbers.

Good Random Generators

Some of the recommended random generators are:

Comparison of Random Generators

Type name Family Period State size Performance Quality Should I use this?
minstd_rand Linear congruential generator 2^31 4 bytes Bad Awful No
mt19937 Mersenne twister 2^19937 2500 bytes Decent Decent Probably (see next section)
ranlux24, ranlux48 Subtract and carry 10^171 96 bytes Awful Good No
knuth_b Shuffled linear congruential generator 2^31 1028 bytes Awful Bad No
default_random_engine Implementation defined Varies Varies ? ? No
rand() Linear congruential generator 2^31 4 bytes Bad Awful No

Popular Choices for PRNGs

Using Mersenne Twister

#include <random> // for std::mt19937
std::mt19937 mt{}; // Instantiate a 32-bit Mersenne Twister
std::cout << mt() << '\t'; // generate a random number

Seeding with the System Clock

#include <chrono> // access to clock

// Seed our Mersenne Twister using steady_clock
std::mt19937 mt{ static_cast<std::mt19937::result_type>(
    std::chrono::steady_clock::now().time_since_epoch().count()
    ) };

// Create a reusable random number generator that generates uniform numbers between 1 and 6
std::cout << die6(mt) << '\t';

Using Random Device for Seeding

#include <random> // for std::mt19937 and std::random_device

std::mt19937 mt{ std::random_device{}() };

std::uniform_int_distribution die6{ 1, 6 }; // for C++14, use std::uniform_int_distribution<> die6{ 1, 6 };
std::cout << die6(mt) << '\t'; // generate a roll of the die here

Common Issues with RNGs

Conclusion

Understanding random number generators and their proper usage is essential for many applications. This chapter covered various RNGs, how to seed them correctly, and best practices to avoid common pitfalls.