c++11 이전에 난수 생성은 기본 난수 함수인 rand()를 주로 써왔습니다. 근데 이 난수 함수는 균일하지도 하고, 몇몇 문제점을 유발하기도 했죠. 그래서 c++11에서는 이런 문제점들을 해결한 여러 난수 함수 라이브러리가 추가되었습니다.


먼저 예제를 보죠.

#include <random>
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 6);
for (int n = 0; n < 10; ++n)
	std::cout << dis(gen) << ' ';


이전 rand() 함수를 사용할 때와는 다르게 좀 복잡해진 것을 볼수 있습니다. 먼저 난수 생성기인 mt19937이 눈에 띄일 것입니다. 흔히 메르센 트위스터라 불리는 난수 생성 방식입니다. 난수 생성이 균일하며, 속도면에서도 빠르죠. c++11 이후로 기본적인 난수 생성기가 될 것입니다. 이외에도 여러 난수 생성기를 제공합니다.



그 다음 살펴볼것이 분포 클래스입니다. 예제에서는 uniform_int_distribution 가 사용되었죠. 이름 그대로 유니폼하게 정수형 난수가 생성된 다는 것입니다. 지정해준 값 1에서 6사이의 값이 동일한 확률로 생성됩니다. 분포 클래스도 용도에 따라 아래와 같이  다양하게 제공되고 있습니다.



유니폼 분포 클래스 말고도 자주 사용 될것 같은 것중 하나가 discrete_distribution 일 것 입니다. 확률 분포 클래스입니다. 게임에서 가챠를 구현한다면, 1번 아이템이 나올 확률은 50%, 2번 아이템 나올 확률은 30%, 가장 좋은 아이템이 나올 확률은 5% 이런식으로 구현을 하는 경우가 많을 겁니다. 그럴때 discrete_distribution 분포 클래스를 사용하는 것이죠.


#include <random>
std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> d({ 50, 30, 15, 5 });
std::map<int, int> m;
for (int n = 0; n < 10000; ++n) {
	++m[d(gen)];
}
for (auto p : m) {
	std::cout << p.first << " generated " << p.second << " times\n";
}


discrete_distribution 분포 클래스를 선언할 때, 가중치를 넣어줍니다. 예제와 같이 50, 30, 15, 5 순으로 입력해주면,


0이 되올 확률 50,

1이 나올 확률 30,

2가 나올 확률 15,

5가 나올 확률 5


가 됩니다.


위 예제를 실행해본 결과는 아래와 같습니다.



출처: https://en.cppreference.com/w/cpp/numeric/random

+ Recent posts