Background knowledge
Generation of random numbers
The C++ standard library provides a powerful and flexible random number tool, mainly composed of the following parts:
-
Random number engine:For example
std::mt19937
, generate a sequence of pseudo-random numbers. -
distributed:For example
std::uniform_int_distribution
, perform distribution conversion on random numbers. - Random number seeds: Used to initialize the random number engine to ensure randomness.
Class design principles
When designing a general random tool class, we can encapsulate common random operations, such as:
- Generates integers or floating-point numbers in the specified range.
- Generates boolean values by probability.
- Randomly disrupt the container.
Class definition and functional decomposition
The following isRandom
Complete definition of class:
#include <chrono> #include <iostream> #include <random> #include <algorithm> struct Random { std::mt19937 rnd; Random() : rnd(std::chrono::steady_clock::now().time_since_epoch().count()) {} void setSeed(unsigned int seed) { (seed); } int operator()(int l, int r) { return std::uniform_int_distribution(l, r)(rnd); } double operator()(double l, double r) { return std::uniform_real_distribution(l, r)(rnd); } bool operator()(double p) { return std::bernoulli_distribution(p)(rnd); } template<typename T> void operator()(std::vector<T>& vec) { std::shuffle((), (), rnd); } };
Below, we will disassemble and explain its core parts one by one.
Initialization of random number engine
Random() : rnd(std::chrono::steady_clock::now().time_since_epoch().count()) {}
std::mt19937
:std::mt19937
It is a pseudo-random number generator based on Mason's rotation algorithm, with good performance and randomness. Its name comes from the generation of a periodic sequence of 19937 bits.-
Initialize seeds:
- The current timestamp (in nanoseconds) is used as the seed by default.
- Timestamp pass
std::chrono::steady_clock
Get to ensure that the seeds are out of sync.
Set random number seeds
void setSeed(unsigned int seed) { (seed); }
-
Seed control randomness:
- Given the same seed, the random number generation sequence is deterministic.
- This feature is ideal for debugging and reproducible experiments.
Generate random integers
int operator()(int l, int r) { return std::uniform_int_distribution(l, r)(rnd); }
-
std::uniform_int_distribution
:- Used to generate uniformly distributed integers.
- The constructor parameters are upper and lower bounds
[l, r]
。
Call method:
Distribute objectsdist
is a callable object. By passing in the random enginernd
, a random number can be generated.
Example:
Random random; int number = random(1, 10); // Generate random integers in the range [1, 10]
Generate random floating point numbers
double operator()(double l, double r) { return std::uniform_real_distribution(l, r)(rnd); }
-
std::uniform_real_distribution
:- Used to generate uniformly distributed floating point numbers.
- The constructor parameters are upper and lower bounds
[l, r)
, that is, the lower realm is closed and the upper realm is opened.
Example:
Random random; double value = random(0.0, 1.0); // Generate random floating point numbers in the range [0.0, 1.0)
Generate boolean values by probability
bool operator()(double p) { return std::bernoulli_distribution(p)(rnd); }
-
std::bernoulli_distribution
:- According to the given probability
p
returntrue
orfalse
。 - Constructor parameters
p
Indicates returntrue
The probability of , range[0, 1]
。
- According to the given probability
Example:
Random random; bool result = random(0.7); // 70% probability returns true, 30% probability returns false
Randomly disrupt containers
template<typename T> void operator()(std::vector<T>& vec) { std::shuffle((), (), rnd); }
-
std::shuffle
:- Random arrangement of container elements.
- use
rnd
Engine, ensure pseudo-randomity.
Template design:
Allow for anystd::vector<T>
Types of containers operate.
Example:
Random random; std::vector<int> vec = {1, 2, 3, 4, 5}; random(vec); // Random disrupt vec
Use scenarios
Random assignment of tasks
Suppose there are 10 tasks that need to be randomly assigned to 3 employees:
Random random; std::vector<int> tasks = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; random(tasks); for (int i = 0; i < (); ++i) { std::cout << "Task " << tasks[i] << " -> Employee " << random(1, 3) << "\n"; }
Simulation coin toss
Random random; int heads = 0, tails = 0; for (int i = 0; i < 100; ++i) { if (random(0.5)) { ++heads; // front } else { ++tails; // The opposite } } std::cout << "Heads: " << heads << ", Tails: " << tails << "\n";
summary
Through the analysis of this article, we have a deeper understanding of the following aspectsRandom
Class design and implementation:
- use
std::mt19937
The random number engine generates high-quality pseudo-random numbers. - Generate random numbers of specific ranges or distributions using distribution objects in the C++ standard library.
- Encapsulate commonly used random functions to improve code readability and reusability.
This is the end of this article about C++'s modern packaging for random number generation. For more relevant content on C++'s modern packaging, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!