Programming Language/C/C++

[C/C++] 난수 생성하기, rand(), srand()

깐요 2017. 6. 2. 17:12

난수 생성하기

확률을 이용하는 프로그램을 작성할 때 난수를 생성할 필요가 있다

난수란 정의된 범위 내에서 무작위로 추출된 수를 말한다 [출처: 위키백과]

난수는 어떻게 생성할까?

난수를 생성해주는 함수는 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에서도 예제로 다룬다)



320x100