Introduction
Learning how to get random number in cpp is a fundamental skill for any programmer who wants to write games, simulations, or any application where unpredictability matters. That's why the C++ Standard Library provides a modern, type‑safe way to generate random values through the <random> header, which replaces the old C‑style rand() function. In this article we will walk through the essential steps, explain the underlying concepts, and answer common questions so you can confidently implement random number generation in your own projects.
It sounds simple, but the gap is usually here.
Steps
1. Include the <random> Header
To start, add the following line to your source file:
#include
The <random> header contains all the classes and functions needed for high‑quality random number generation.
2. Choose a Random Engine
C++ offers several engine classes, the most popular being std::mt19937 (Mersenne Twister). This engine produces a pseudo‑random sequence that is fast and has a long period. You can also use std::minstd_rand or std::ranlux, but mt19937 is a safe default It's one of those things that adds up..
std::mt19937 rng; // create an engine instance
3. Seed the Engine
A seed provides the starting point for the sequence. If you seed with a constant, the same sequence will appear every time—useful for debugging. For true variability, combine the current time with a high‑resolution clock:
std::random_device rd; // obtains a non‑deterministic seed if available
std::mt19937 rng(rd()); // seed with random_device
// or, for a deterministic seed:
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
4. Define a Distribution
Engines alone produce raw bits; you need a distribution to map those bits to meaningful values such as integers, floating‑point numbers, or booleans. Common distributions include:
std::uniform_int_distribution<int>– uniform integer rangestd::uniform_real_distribution<double>– uniform floating‑point rangestd::normal_distribution<double>– Gaussian (bell‑curve) values
Example for a uniform integer between 1 and 100:
std::uniform_int_distribution dist(1, 100);
int random_value = dist(rng);
5. Generate Random Numbers
Now you can call the distribution with your engine:
for (int i = 0; i < 5; ++i) {
std::cout << dist(rng) << ' ';
}
Each call produces a new value that respects the defined range and distribution.
6. Reuse the Engine and Distribution
You do not need to recreate the engine or distribution for each number. Instantiating them once and reusing them improves performance and ensures statistical quality Not complicated — just consistent..
Scientific Explanation
Pseudo‑Random vs. True Random
The term pseudo‑random means the numbers are deterministic and reproducible when the same seed is used. g.True randomness comes from physical processes (e., thermal noise) and is accessed via std::random_device. In practice, a good pseudo‑random engine like mt19937 is sufficient for most software because its period is 2^19937‑1, far beyond any realistic need It's one of those things that adds up..
Entropy and Seed Quality
The quality of the seed directly influences the randomness of the output. If that source is unavailable (e.g.Even so, using std::random_device attempts to harvest entropy from the operating system, giving a more unpredictable start. , on some embedded platforms), mixing the current time with other variables is a reasonable fallback.
Uniform Distribution
A uniform distribution means each outcome in the specified range has equal probability. This is the simplest form of randomness and is often the default choice when you need a fair dice roll or a random index Most people skip this — try not to..
Non‑Uniform Distributions
For many simulations (e.g., modeling heights, test scores), a normal distribution better reflects real‑world phenomena. The std::normal_distribution transforms the engine’s output into a bell‑shaped curve, preserving the statistical properties needed for accurate results.
FAQ
Q1: Can I still use rand() and srand() in modern C++?
A: Yes, they are still available via <cstdlib>, but they are considered legacy. rand() uses a simple linear congruential generator that has poorer statistical properties and limited range compared to <random>.
Q2: Why does my random number look the same each run?
A: The engine was likely seeded with a constant value. Ensure you seed with a varying source such as std::random_device or the current time.
Q3: Is std::mt19937 thread‑safe?
A: No. The engine maintains internal state, so concurrent access from multiple threads can cause race conditions. Protect the engine with a mutex or use thread‑local
storage so that each thread gets its own independent engine instance. This avoids data races while keeping each stream reproducible within its thread.
Conclusion
Modern C++ random number generation is built around a clear separation between engines and distributions. By seeding a high‑quality engine such as std::mt19937 with a source of entropy, reusing both the engine and distribution objects, and selecting the distribution that matches your problem domain, you can produce statistically sound random numbers for simulations, games, sampling, and more. Legacy functions like rand() remain available, but they lack the range, flexibility, and statistical rigor of <random>. When sharing generators across threads, protect them with synchronization or give each thread its own thread_local engine. Following these practices gives you reliable, performant randomness without sacrificing correctness.