난수 만들기 (Random Number Generation)
실행할 때마다 다른 난수 생성하기
#include <iostream>
#include <cstdlib> // std::rand(), std::srand()
#include <ctime> // std::time()
using namespace std;
int main()
{
std::srand(static_cast<unsigned int>(std::time(0)));
for (int count = 1; count <= 100; ++count)
{
cout << std::rand() << "\t";
if (count % 5 == 0) cout << endl;
}
return 0;
}
실행시킬 때마다 다른 난수를 생성하기 위해서 시드넘버에 고정된 숫자를 사용하는 대신
srand에 seed number를 현재 시간과 연결시키는 방법이 있다.
다만 디버깅이 필요하다면 시드 넘버를 고정시키고 반복을 시키면 된다.
특정 정수 사이의 난수 생성하기
#include <iostream>
#include <cstdlib> // std::rand(), std::srand()
#include <ctime> // std::time()
using namespace std;
int getRandomNumber(int min, int max)
{
static const double fraction = 1.0 / (RAND_MAX + 1.0);
return min + static_cast<int>((max - min + 1) * (std::rand() * fraction));
}
int main()
{
std::srand(static_cast<unsigned int>(std::time(0)));
for (int count = 1; count <= 100; ++count)
{
cout << getRandomNumber(5,8) << "\t";
if (count % 5 == 0) cout << endl;
}
return 0;
}
static으로 선언한 fraction을 static을 빼고 전역 상수로 선언해도 상관없다.
RAND_MAX
RAND_MAX는 난수를 생성할때 나올 수 있는 가장 큰 숫자를 의미한다. 매크로로 정의되어있다.
C언어 스타일로 특정범위의 난수를 생성하는 방법으로는
cout << rand() % 4 + 5 << "\t";
이 방법도 있다. 숫자범위가 작을때는 상관없지만 큰 범위의 숫자 내에서 난수를 생성할때는
난수가 특정 영역으로 몰리는 문제가 생길 수도 있다.
그래서 정밀함이 필요할 경우에는 random library를 사용하는게 좋다.
random 라이브러리 사용
#include <iostream>
#include <cstdlib> // std::rand(), std::srand()
#include <ctime> // std::time()
#include <random>
using namespace std;
int main()
{
std::random_device rd;
std::mt19937 mersenne(rd());
std::uniform_int_distribution<> dice(1,6);
for (int count = 1; count <= 20; ++count)
cout << dice(mersenne) << endl;
return 0;
}
아까는 실행할 때마다 난수가 변하게 만들기 위해 time을 연동시켰지만,
여기서는 별도의 random divece를 제공해주고 있다.
mt19937은 32비트 짜리 난수를 생성해준다.
(mt19937_64는 64비트 난수를 생성해준다.)
mersenne은 mersenne twister 알고리즘을 개발한 수학자 이름이고
여기선 변수명이므로 바꿀 수 있다. 여기선 seed를 random_device를 사용하기 때문에
같은 난수 패턴이 발생되는것을 막는다.
uniform_int_distribution<> dice(1,6)은 1부터 6까지 숫자를 모두 동일한 확률로
나오게 한다.
난수를 만드는 순서와 각 줄의 기능을 정리해 보자.
- 랜덤 디바이스 만들기
std::random_device rd;
- 생성기를 만들고 랜덤 디바이스를 넣기
std::mt19937 mersenne(rd());
- 생성기가 어떤 분포를 따를지 정해서 사용할 분포를 만들기
std::uniform_int_distribution<> dice(1,6);
- 분포가 생성기를 통해 난수 생성
dice(mersenne)
'C++' 카테고리의 다른 글
6-1. C언어 스타일 배열 문자열(strcpy, strcat, strcmp) (0) | 2024.02.17 |
---|---|
5-3. C++ std::cin.fail(), std::cin.clear(), std::cin.ignore() 함수 (0) | 2024.02.07 |
5-1. C++ switch-case, do-while (0) | 2024.02.03 |
4-3. C++ 자료형에게 가명 붙이기 (type aliases), 구조체 (struct) (0) | 2024.02.02 |
4-2. C++ 문자열, 열거형, 열거형 클래스 (1) | 2024.02.02 |