난수 생성하기
확률을 이용하는 프로그램을 작성할 때 난수를 생성할 필요가 있다
난수란 정의된 범위 내에서 무작위로 추출된 수를 말한다 [출처: 위키백과]
난수는 어떻게 생성할까?
난수를 생성해주는 함수는 rand()라는 함수가 있다
rand() 함수의 원형은 stdlib.h 또는 cstdlib (C++) 파일에 포함되어 있다
#include <iostream> #include <cstdlib> int main() { std::wcout << rand() << std::endl; }
위 코드를 실행하면 0 ~ 32767 사이의 난수가 생성된다는 것을 알 수 있다
cstdlib에 포함되어 있는 RAND_MAX의 상수값은 0x7fff 즉, 32767이다
MSDN"rand"::https://msdn.microsoft.com/ko-kr/Library/398ax69y.aspx
그러나 다시 한 번 컴파일 했을 때 이상한 점이 발견된다
컴파일을 재시도해도 같은 수가 나온다?
컴파일할 때마다 난수 생성 값을 다르게 해주기 위해서는 시드(seed) 값을 부여해주어야 한다
이와 관련된 함수로는 srand() 함수가 있다
이 함수의 원형도 역시 cstlib에 포함되어 있다
MSDN"srand"::https://msdn.microsoft.com/ko-kr/library/f0d4wb4t.aspx
매 컴파일마다 다른 시드값을 주기 위해서는 time() 함수를 통해 컴파일되는 시간을 따져볼 필요가 있다
time() 함수의 원형은 time.h 또는 ctime (C++) 에 포함되어 있으며
1970년 1월 1일 자정 이후 경과된 시간을 반환하거나 오류가 날 경우 -1 을 반환한다
매개 변수가 NULL이나 0일 경우에는 반화된 값을 저장하지 않으므로 time_t형 변수를 필요로 하지 않는다
MSDN"time, _time32, _time64"::https://msdn.microsoft.com/ko-kr/library/1f4c8f33.aspx
#include <iostream> #include <cstdlib> #include <ctime> int main() { srand(time(0)); std::wcout << rand() << std::endl; }
위 코드를 컴파일해보면 매번 다른 난수가 생성되는 것을 확인할 수 있다
정해진 범위 내의 난수
보통의 rand() 함수는 RAND_MAX 까지의 난수를 생성하기 때문에 원하는 범위의 난수를 얻기 어렵다
범위를 한정하기 위해서는 간단한 수학 식을 이용하면 된다
흔히 rand() % n 을 사용하지만 이는 완전히 옳은 방식이 아니다
n의 값이 커질수록 편차가 적어져 무작위성이 약해진다
예를 들어 n이 10000 인 경우에는 0 ~ 29999 범위에서는 경우의 수가 같지만
30000 ~ 32767 까지는 0 ~ 2767 경우만 있으므로 분포가 치우쳐져 있다
ljh131@blog"rand() % n은 쓰지말자 왜?"::http://ljh131.tistory.com/131
이 문제를 해결하는 방법은 rand() 를 이용하여 0 ~ 1 사이의 실수형에서 원하는 범위를 곱하는 형태로 바꾸면 된다
#include <iostream> #include <cstdlib> #include <ctime> int main() { srand(time(0)); rand(); const int MAX = 100 const int MIN = 10; int r = (double)rand() / RAND_MAX * (MAX - MIN) + MIN //10 ~ 100 까지의 난수 std::wcout << r << std::endl; }
srand() 함수 다음에 rand() 함수를 써주었는데
그 이유는 시드값이 현재 시간에 의해 바뀌므로 단시간에 여러 번 컴파일할 경우 첫 난수의 값의 차이는 이전 컴파일 시의 값과 큰 차이가 없는 난수가 생성되기 때문이다
(실제로 Java의 rand() 함수는 위와 같은 방법을 지원하고 MSDN에서도 예제로 다룬다)
'Programming Language > C/C++' 카테고리의 다른 글
[C++] export와 클래스 템플릿, 헤더 파일 나누기 (1) | 2017.07.14 |
---|---|
[C/C++] char[] 문자열 초기화시 주의할 점 (0) | 2017.06.15 |
[C/C++] 한글 출력 오류, 유니코드, MBCS, 국제화 (3) | 2017.06.01 |
[C++] 연산자 오버로딩과 프렌드 (0) | 2017.06.01 |
[C/C++] namespace 제대로 사용하기 (0) | 2017.05.23 |