C++ random | Engines, distributions, and replacing rand()

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/)