-
Notifications
You must be signed in to change notification settings - Fork 4
C & CPP 난수 생성
FoRA edited this page Jan 3, 2021
·
1 revision
C에서와 C++에서의 난수 생성은 다르다(물론 C++에서 C에서의 방법도 되긴 된다).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
for (int i = 0; i < 5; i++) {
printf("난수 : %d \n", rand() % 100);
}
return 0;
}
위 코드는 난수를 생성하는 것이 아닌 난수 처럼 보이는 의사 난수(pseudo random number)을 생성하는 코드다. 첫 번째 수만 무작위로 정하고, 나머지 수들은 그 수를 기반으로 여러가지 수학적 방법을 통해 난수 처럼 보이는 수열을 만드는 것이다.
- 무작위로 정해진 첫 번째 수를 시드(seed)라고 한다. C의 경우
srand
를 통해seed
를 설정할 수 있다.time(Null)
을 통해 프로그램을 실행했던 초를 시드값으로 지정하면 무작위로 숫자가 하나 정해지고rand()
는 호출 할 때마다 시드값을 기반으로 무작위처럼 보이는 수열을 생성한다.
하지만 다음의 문제점이 있다.
- 같은 시간대에 시작된 프로그램의 경우 모두 같은 의사 난수 수열을 생성한다.
- 0 부터 99 까지 균등하게 난수를 생성하지 않는다.
-
rand()
자체도 별로 뛰어나지 않다.-
randn()
함수는 선형 합동 생성기(Linear congruential generator) 이라는 알고리즘을 바탕으로 구현되어 있는데 이 알고리즘은 좋은 품질의 난수열을 생성 못한다.
-
- 자세한 것은 Reference 참고
C++ 에서는 C 의 srand 와 rand 는 갖다 버리자!
#include <iostream>
#include <random>
using namespace std;
int main() {
// 시드값을 얻기 위한 random_device 생성.
random_device rd;
// random_device 를 통해 난수 생성 엔진을 초기화 한다.
mt19937 gen(rd());
// 0 부터 99 까지 균등하게 나타나는 난수열을 생성하기 위해 균등 분포 정의.
uniform_int_distribution<int> dis(0, 99);
for (int i = 0; i < 5; i++) {
cout << "난수 : " << dis(gen) << endl;
}
}
- C++ 에서는 좀더 양질의 시드값을 얻기 위해
random_device
라는 것을 제공한다. - 만들어진
random_device
객체인rd
를mt19937 gen()
의 시드값으로 준다.- 만약 시드 값을 1234로 지정하고 싶다면
mt19937 gen(1234)
로 하면 된다. - mt19937은 메르센 트위스터라는 알고리즘을 사용한다.
- 이 알고리즘은 좋지만 mt19937 객체가 크기가 커서(2KB 이상) 메모리가 부족하다면
minstd_rand
도 괜찮다.
- 만약 시드 값을 1234로 지정하고 싶다면
- C++ 의 경우 어디에서 수들을 뽑아낼지 알려주는 분포(distribution) 을 정의해야 한다.
- 만약 0 ~ 100까지 균등한 확률 분포로 뽑는다면 균등 분포 (Uniform distribution) 객체를 정의해야 한다.
uniform_int_distribution<int> dis(0, 100);
- 이후
dis(gen)
을 통해 생성된 난수를 사용할 수 있다.