--프로그래밍--/C, C++

[C++] rand()는 이제 그만 ! 난수 엔진 mt19937

Prog_K 2015. 1. 29. 11:28

C 표준 rand 함수

 

C/C++ 응용 프로그램을 작성할 때 '랜덤 함수' 또는 '난수 생성기' 하면 가장 먼저 떠오르는 것이 바로 C 표준 라이브러리의 rand 함수입니다. 그만큼 rand 함수가 널리 사용되고있고 우리에게 익숙하다는 얘기겠죠. 하지만 rand 함수는 다음과 같은 문제점을 가지고 있습니다. 

 

  • 생성된 난수의 분포가 그리 고르지 않다.
  • 반복 주기는 2^32 로 다른 유사 난수 생성기에 비해 상대적으로 짧다.
  • 전역 함수이기 때문에 프로그램 전체에서 시드를 공유한다.

 

 

난수의 품질이 크리티컬한 영향을 미치는 과학 계산 프로그램이 아니라면 난수 분포와 반복 주기는 그리 중요한 부분이 아닐 수도 있습니다. 특별한 상황이 아니라면 프로그램 전체에서 시드를 공유하는 것도 크게 문제가 될만한 부분도 아니죠. 하지만 C#과 Java의 Random 객체와 비교해보면 전역 함수 rand로 난수를 생성하는 방식은 너무 구닥다리 같아보입니다. 하지만 C++은 꾸준히 발전해왔고 이에 대한 여러가지 대안은 이미 준비되어 있습니다. 이 문서에서는 그 중 대표적인 방식 한가지를 소개하고자 합니다.

  

 

Mersenne Twister

 

'메르센 트위스터(Mersenne Twister)는 1997년에 마츠모토 마코토와 니시무라 다쿠지가 개발한 유사난수 생성기로 기존 생성기들의 문제점들을 피하면서 매우 질이 좋은 난수를 빠르게 생성할 수 있도록 설계되었다.' 라고 위키 백과에 설명되어 있으며 속도와 난수의 품질 때문에 점점 많은 곳에서 채택되고 있습니다.

 

메르센 트위스터 중에서도 MT19937이 주로 사용되는데 이는 2^19937-1 의 주기를 가지며 623차원까지 동일 분포되어있습니다. 이 수치를 정확히 이해하지는 못하겠지만 엄청나게 큰 반복 주기와 고른 분포를 가진다는 것으로 해석할 수 있겠네요. 게다가 비트 연산만으로 알고리즘을 구현하기 때문에 속도도 매우 빠르다고 합니다. 자세한 내용은 문서 하단에 링크된 위키 백과를 참고하시기 바랍니다.

 

 

C++0x 기본 난수 엔진 mt19937

 

메르센 트위스터는 이미 boost 라이브러리에서 mersenne_twister 클래스로 구현되었고 그중에서도 주로 사용된다는 MT19937은 mt19937 이라는 이름으로 typedef 되어져 있습니다. 그리고 이것는 TR1의 <random> 에도 포함되었고 TR1에서는 다음과 같은 코드를 작성하여 난수를 생성할 수 있었습니다.

 

 

 C++0x로 넘어오면서 mt19937은 그 성능을 인정 받아 기본 난수 엔진으로 채택되었으며 default_random_engine 이라는 이름으로도 typedef 되어집니다. 그리고 <random> 의 최종적인 표준에서는 variate_generator를 더이상 사용하지 않는 대신 bind 함수를 이용하여 generator를 생성하도록 변경되었고, uniform_int<> 은 uniform_int_distribution<int> 로 대체되었습니다. Visual Studio 2012 버전에서는 위에서 작성한 코드는 더이상 컴파일되지 않습니다. 그럼 코드를 다시 작성해보도록 하죠.

지금까지 기존 C 표준 rand 함수를 대체하는 목적의 간단한 코드를 통해 mt19937의 사용법을 소개해드렸습니다. <random> 라이브러리 안에는 mt19937을 비롯한 많은 난수 엔진이 포함되어 있으니 시간이 되시면 다른 항목에 대해서도 한 번 살펴보시기 바랍니다.

 

 

Reference

 

위키백과 - 메르센 트위스터

위키백과 - Extensible random number facility

표준 rand()함수보다 유용한 랜덤 생성 알고리즘 – MT, WELL

 

 

원문 링크

 

DevMachine's Blog

 

 

http://loveseulji.tistory.com