Random in C++ 11



random값을 뽑을 때, 기존 c 런타임의 srand()와 rand()를 이용했는데 c++ 11에서는 아래처럼 사용할 수 있다.

1
2
3
4
5
6
7
8
//c runtime
srand((unsigned int)time(0));
int i = rand();
 
//c++ 11
std::default_random_engine e((unsigned int)time(0));
  //or
std::default_random_engine e(std::random_device{}());

srand()는 인자로 받아온 seed값으로 의사 난수(pseudo random number)기를 초기화 한다. std::default_random_engine은 의사 난수를 생성하는 클래스다.

위 둘은 난수 발생기의 위치가 어디에 있느냐에 그 차이가 있다.
rand()는 내부에 의사 난수기의 상태를 static data로 가지고 있기 때문에 멀티 스레드에 안전하도록 내부적인 장치가 있다.
이에 반해, default_random_engine은 우리가 직접 다룰 수 있다. 스택에 생성했다면 동기화 처리도 필요없다. 그래서 동기화할 필요가 없는 상황이라면 default_random_engine이 rand()보다 더 빠르다고 한다.

게임에서 특정 정보 등을 랜덤하게 가져와 사용한다고 하면, 아래처럼 쓸 수 있겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
struct SkillInfo
{
    int id_;
    string name_;
};
 
int main()
{
    vector<SkillInfo> skill_Info = 
    {
        { 3001, "섬멸" },
        { 3013, "중독" },
        { 3018, "소환" },
        { 3035, "투명" },
        { 3073, "질주" }
    };
 
    std::default_random_engine engine(std::random_device{}());
    auto GetRanomSkillInfo = [&]()
    {
        std::shuffle(skill_Info.begin(), skill_Info.end(), engine);
    };
 
    auto PrintSkillInfo = [&skill_Info]()
    {
        for_each(skill_Info.begin(), skill_Info.end(), [&](const SkillInfo& info)
        {
            cout << "id = " << info.id_ << ", name = " << info.name_ << endl;
        });
    };
 
    for (int i = 0; i < 10; i++)
    {
        cout << "==========" << endl;
        GetRanomSkillInfo();
        PrintSkillInfo();
    }
     
    getchar();
 
    return 0;
}

아래 링크에, C++ 11에서 random number 사용에 관한 12 page짜리(!) guide 문서가 있다.
Random Number Generation in C++ 11