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
가 됩니다.
위 예제를 실행해본 결과는 아래와 같습니다.