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.
Some of the recommended random generators are:
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 |
#include <random> // for std::mt19937
std::mt19937 mt{}; // Instantiate a 32-bit Mersenne Twister
std::cout << mt() << '\t'; // generate a random number
#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';
#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
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.