C++ random | Engines, distributions, and replacing rand()
이 글의 핵심
Hands-on guide to the C++11 random library: seed once, reuse engines and distributions, reproducible simulations, and thread-local engines.
What is Random?
The C++11 <random> library is a standard library for high-quality random number generation. More powerful and flexible than C-style rand().```cpp
#include
std::random_device rd; std::mt19937 gen{rd()}; std::uniform_int_distribution<> dist{1, 6};
int dice = dist(gen); // 1~6
- Quality: Ensure equal distribution
- Flexibility: Supports various distributions
- Reproducibility: Reproduce results with seeds
- Type safe: template based```cpp
// ❌ rand(): 비균등, 예측 가능
int r = rand() % 100; // 0~99 (비균등)
// ✅ C++11 random: 균등, 고품질
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<> dist{0, 99};
int r = dist(gen); // 0~99 (균등)
```Random Structure:```mermaid
flowchart LR
A[random_device] -->|시드| B[엔진 mt19937]
B -->|난수| C[분포 uniform_int_distribution]
C -->|최종 난수| D[결과]
```3-step structure:
| steps | Role | Example |
|------|------|------|
| 1. Seed | Create initial value | `std::random_device rd;` |
| 2. Engine | random number generation | `std::mt19937 gen{rd()};` |
| 3. Distribution | Range adjustment | `std::uniform_int_distribution<> dist{0, 99};` |```cpp
// 1. 시드: 하드웨어 엔트로피
std::random_device rd;
// 2. 엔진: 메르센 트위스터
std::mt19937 gen{rd()};
// 3. 분포: 0~99 균등 분포
std::uniform_int_distribution<> dist{0, 99};
// 4. 생성
int random = dist(gen);
```## Basic structure```cpp
#include <random>
// 1. 시드
std::random_device rd;
// 2. 엔진
std::mt19937 gen{rd()};
// 3. 분포
std::uniform_int_distribution<> dist{0, 99};
// 4. 생성
int random = dist(gen);
```## Practical example
### Example 1: Dice```cpp
#include <random>
class Dice {
std::mt19937 gen;
std::uniform_int_distribution<> dist;
public:
Dice() : gen{std::random_device{}()}, dist{1, 6} {}
int roll() {
return dist(gen);
}
};
int main() {
Dice dice;
for (int i = 0; i < 10; ++i) {
std::cout << dice.roll() << " ";
}
}
```### Example 2: Ranged random numbers```cpp
#include <random>
int randomInt(int min, int max) {
static std::random_device rd;
static std::mt19937 gen{rd()};
std::uniform_int_distribution<> dist{min, max};
return dist(gen);
}
double randomDouble(double min, double max) {
static std::random_device rd;
static std::mt19937 gen{rd()};
std::uniform_real_distribution<> dist{min, max};
return dist(gen);
}
int main() {
std::cout << randomInt(1, 100) << std::endl;
std::cout << randomDouble(0.0, 1.0) << std::endl;
}
```### Example 3: Shuffle```cpp
#include <random>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> cards = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::random_device rd;
std::mt19937 gen{rd()};
std::shuffle(cards.begin(), cards.end(), gen);
for (int card : cards) {
std::cout << card << " ";
}
}
```### Example 4: Weight selection```cpp
#include <random>
#include <vector>
int main() {
std::vector<int> items = {1, 2, 3, 4, 5};
std::vector<double> weights = {0.1, 0.2, 0.3, 0.2, 0.2};
std::random_device rd;
std::mt19937 gen{rd()};
std::discrete_distribution<> dist{weights.begin(), weights.end()};
// 가중치에 따라 선택
for (int i = 0; i < 10; ++i) {
int index = dist(gen);
std::cout << items[index] << " ";
}
}
```## Random number engine```cpp
// mt19937: 메르센 트위스터 (권장)
std::mt19937 gen;
// mt19937_64: 64비트
std::mt19937_64 gen64;
// default_random_engine
std::default_random_engine gen_default;
// minstd_rand: 선형 합동
std::minstd_rand gen_lcg;
```## Frequently occurring problems
### Problem 1: Seed```cpp
// ❌ 고정 시드
std::mt19937 gen{42}; // 항상 같은 난수
// ✅ random_device
std::random_device rd;
std::mt19937 gen{rd()};
// ✅ 시간 기반 (비권장)
std::mt19937 gen{static_cast<unsigned>(std::time(nullptr))};
```### Issue 2: Global State```cpp
// ❌ 매번 생성
int random() {
std::random_device rd;
std::mt19937 gen{rd()}; // 느림
std::uniform_int_distribution<> dist{0, 99};
return dist(gen);
}
// ✅ static
int random() {
static std::random_device rd;
static std::mt19937 gen{rd()};
static std::uniform_int_distribution<> dist{0, 99};
return dist(gen);
}
```### Problem 3: Distribution reuse```cpp
std::mt19937 gen{std::random_device{}()};
// ❌ 분포 재생성
for (int i = 0; i < 100; ++i) {
std::uniform_int_distribution<> dist{0, 99};
int r = dist(gen);
}
// ✅ 분포 재사용
std::uniform_int_distribution<> dist{0, 99};
for (int i = 0; i < 100; ++i) {
int r = dist(gen);
}
```### Problem 4: Using rand()```cpp
// ❌ rand() (C 스타일, 비권장)
int r = rand() % 100; // 균등하지 않음
// ✅ C++11 random
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<> dist{0, 99};
int r = dist(gen);
```## Distribution type```cpp
// 정수
std::uniform_int_distribution<> uniform{0, 99};
std::binomial_distribution<> binomial{10, 0.5};
std::poisson_distribution<> poisson{4.0};
// 실수
std::uniform_real_distribution<> uniformReal{0.0, 1.0};
std::normal_distribution<> normal{0.0, 1.0};
std::exponential_distribution<> exponential{1.0};
// 불리언
std::bernoulli_distribution bernoulli{0.7};
```## Practice pattern
### Pattern 1: Game random numbers```cpp
class GameRandom {
std::mt19937 gen_;
public:
GameRandom() : gen_{std::random_device{}()} {}
// 주사위
int rollDice(int sides = 6) {
std::uniform_int_distribution<> dist{1, sides};
return dist(gen_);
}
// 확률 (0.0 ~ 1.0)
double chance() {
std::uniform_real_distribution<> dist{0.0, 1.0};
return dist(gen_);
}
// 크리티컬 히트 (20% 확률)
bool criticalHit() {
std::bernoulli_distribution dist{0.2};
return dist(gen_);
}
};
// 사용
GameRandom rng;
int damage = rng.rollDice(20); // 1d20
if (rng.criticalHit()) {
damage *= 2;
}
```### Pattern 2: Sampling```cpp
#include <random>
#include <vector>
#include <algorithm>
template<typename T>
std::vector<T> randomSample(const std::vector<T>& data, size_t n) {
if (n >= data.size()) {
return data;
}
std::vector<T> result = data;
std::random_device rd;
std::mt19937 gen{rd()};
std::shuffle(result.begin(), result.end(), gen);
result.resize(n);
return result;
}
// 사용
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto sample = randomSample(data, 3); // 3개 무작위 선택
```### Pattern 3: Simulation```cpp
#include <random>
class Simulation {
std::mt19937 gen_;
std::normal_distribution<> normal_;
std::exponential_distribution<> exponential_;
public:
Simulation(unsigned seed = std::random_device{}())
: gen_{seed},
normal_{0.0, 1.0}, // 평균 0, 표준편차 1
exponential_{1.0} {} // 람다 1
// 정규 분포 (키, 몸무게 등)
double normalValue() {
return normal_(gen_);
}
// 지수 분포 (대기 시간 등)
double exponentialValue() {
return exponential_(gen_);
}
};
// 사용
Simulation sim;
double height = 170.0 + sim.normalValue() * 10.0; // 평균 170cm
double waitTime = sim.exponentialValue(); // 평균 1초
```## FAQ
### Q1: What is Random?
A: C++11 random number generation library. Generates high-quality random numbers and supports various distributions.```cpp
#include <random>
std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<> dist{0, 99};
int r = dist(gen);
```### Q2: What is the structure?
A: Seed + Engine + Distribution 3-stage structure.```cpp
std::random_device rd; // 1. 시드
std::mt19937 gen{rd()}; // 2. 엔진
std::uniform_int_distribution<> dist; // 3. 분포
int r = dist(gen); // 4. 생성
```### Q3: Which engine should I use?
A: `std::mt19937` (Mersenne Twister) is recommended.```cpp
std::mt19937 gen{std::random_device{}()}; // 32비트
std::mt19937_64 gen64{std::random_device{}()}; // 64비트
```### Q4: Can't I use rand()?
A: Not recommended. `rand()` has issues with uneven distribution, low quality, and global state.```cpp
// ❌ rand(): 비균등
int r = rand() % 100;
// ✅ C++11 random: 균등
std::uniform_int_distribution<> dist{0, 99};
int r = dist(gen);
```### Q5: How do I set the seed?
A: `std::random_device` is recommended.```cpp
// ✅ random_device: 하드웨어 엔트로피
std::random_device rd;
std::mt19937 gen{rd()};
// ❌ 시간 기반: 예측 가능
std::mt19937 gen{static_cast<unsigned>(std::time(nullptr))};
```### Q6: How to generate reproducible random numbers?
A: Uses a fixed seed.```cpp
// 재현 가능
std::mt19937 gen{42}; // 항상 같은 난수
// 테스트에 유용
void testRandom() {
std::mt19937 gen{12345};
// 항상 같은 결과
}
```### Q7: Is it thread safe?
A: Not thread-safe. A separate engine must be used for each thread.```cpp
// ❌ 전역 엔진: 경쟁 조건
std::mt19937 globalGen;
void threadFunc() {
int r = std::uniform_int_distribution<>{0, 99}(globalGen); // 위험
}
// ✅ thread_local
thread_local std::mt19937 gen{std::random_device{}()};
void threadFunc() {
int r = std::uniform_int_distribution<>{0, 99}(gen); // 안전
}
```### Q8: What are Random learning resources?
A:
- "C++ Primer" by Stanley Lippman
- "Effective Modern C++" by Scott Meyers
- [cppreference.com - Random](https://en.cppreference.com/w/cpp/numeric/random)
Related posts: [random_device](/blog/cpp-random-device/), mt19937, [distribution](/blog/cpp-distribution/).
One-line summary: C++11 random is a standard library for high-quality random number generation.
---
## Good article to read together (internal link)
Here's another article related to this topic.
- [C++ Distribution | “Probability Distribution” Guide](/blog/cpp-distribution/)
- [C++ random number generation | "random" library guide](/blog/cpp-random-guide/)
- [C++ random_device | “Hardware Random Numbers” Guide](/blog/cpp-random-device/)
## Practical tips
These are tips that can be applied right away in practice.
### Debugging tips
- If you run into a problem, check the compiler warnings first.
- Reproduce the problem with a simple test case
### Performance Tips
- Don't optimize without profiling
- Set measurable indicators first
### Code review tips
- Check in advance for areas that are frequently pointed out in code reviews.
- Follow your team's coding conventions
---
## Practical checklist
This is what you need to check when applying this concept in practice.
### Before writing code
- [ ] Is this technique the best way to solve the current problem?
- [ ] Can team members understand and maintain this code?
- [ ] Does it meet the performance requirements?
### Writing code
- [ ] Have you resolved all compiler warnings?
- [ ] Have you considered edge cases?
- [ ] Is error handling appropriate?
### When reviewing code
- [ ] Is the intent of the code clear?
- [ ] Are there enough test cases?
- [ ] Is it documented?
Use this checklist to reduce mistakes and improve code quality.
---
## Keywords covered in this article (related search terms)
This article will be helpful if you search for C++, random, generator, distribution, C++11, etc.
---
## Related articles
- [C++ Distribution | ](/blog/cpp-distribution/)
- [C++ random_device | ](/blog/cpp-random-device/)
- [C++ random number generation | ](/blog/cpp-random-guide/)
- [C++ async & launch | ](/blog/cpp-async-launch/)
- [C++ Atomic Operations | ](/blog/cpp-atomic-operations/)