프로그래밍 언어/C++

[C++] 난수 생성 방법

riroan 2022. 7. 8. 22:49

C를 먼저 공부하고 C++를 공부하는 사람이라면 난수를 생성할 때 stdlib.h(cstdlib)에 있는 rand 함수를 사용했을 것이다.

rand함수를 사용하면 난수가 생성되는것 처럼 보이지만 실제로 여러번 실행해보면 같은 결과가 나온다.

 

rand함수를 대략적으로 구성하면 다음과 같을 것이다.

int myRand() {
	static int seed = 94263523;
	seed = (seed + 998244353) % (1000000007);
	return seed;
}

여기에서 시드넘버가 일정하기 때문에 언제나 같은 수가 나올 것이고 실행해보면 난수가 생성된것 처럼 보인다.

이를 해결하기 위해 시드넘버를 현재시간 기준으로 설정하곤 한다.

#include<ctime>
int myRand() {
	static int seed = time(nullptr);
	seed = (seed + 998244353) % (1000000007);
	return seed;
}

이제 실행할 때마다 다른 수가 나와서 더 난수에 가까워진 것 같다.

하지만 이러한 로직은 시간에 의존하여 난수를 발생시킨다.

 

C++에서는 위와 같은 단순한 난수 발생에서 벗어나 보다 정교한 난수 생성기를 제공한다.

사용법은 다음과 같다.

#include<iostream>
#include<random>

int main() {
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_int_distribution<int> uid(0, 100);
	for (int i = 0; i < 1000; i++)
		std::cout << uid(gen) << std::endl;
}

random_device : 하드웨어에 기반한 비결정적 난수 발생기이다.

mt19937 : 메르센소수를 이용하여 난수를 발생시킨다. 여기서 메르센소수는 $2^p-1$ ($p$는 소수)인 소수이다. $19937$도 소수이고 $2^{19937}-1$도 매우 큰 메르센 소수이다.

메르센 소수

uniform_int_distribution : 0~100사이 범위의 정수 난수를 균일하게 발생시킨다. (평균적으로 0~100까지 10번씩 나올것이다.)

 

위 코드를 사용하면 보다 정교한 난수생성이 가능해진다.

정수는 물론 실수, 정규분포, 베르누이분포, 푸아송분포등 다양한 생성기도 제공하니 자신에게 필요한 난수 발생기를 이용하도록 하자.

 

* reference

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

 

Pseudo-random number generation - cppreference.com

The random number library provides classes that generate random and pseudo-random numbers. These classes include: Uniform random bit generators (URBGs), which include both random number engines, which are pseudo-random number generators that generate integ

en.cppreference.com

 

 

'프로그래밍 언어 > C++' 카테고리의 다른 글

[C++] 시간 측정 방법  (0) 2022.07.21