Computer Science/C & C++

[C++] Random Number Generation | 난수 생성

lww7438 2020. 2. 29. 14:53

Random Number Generation

난수 생성

- C++에서는 \(\texttt{rand(), srand(), time()}\) 라이브러리로 난수를 발생시키는 프로그램을 작성할 수 있다.
- C++11부터는 \(\texttt{<random>}\) 헤더파일을 통해 확장된 난수 제어 기능을 제공한다.


\(\texttt{rand()}\) Function (\(\texttt{rand()}\) 함수)

- Prototype : \(\texttt{int rand (void);}\)
- C++의 \(\texttt{<cstdlib>}\) 헤더파일에 정의되어 있다.
- 0 ~ 32767 사이의 정수 중 하나의 수를 리턴한다. (32767(\(\texttt{0x7FFF}\))은 헤더파일 내에 기호상수로 \(\texttt{RAND_MAX}\)라 정의되어 있다.)
- 소스코드가 컴파일될 때, 하나의 \(\texttt{rand()}\) 함수 마다 하나의 값으로 지정되므로 프로그램을 여러번 실행시켜도 동일한 매번 같은 값을 리턴한다.

// Ex. rand() 함수 사용 예시

#include <iostream>
#include <cstdlib>

int main(){
    std::cout << rand() << std::endl;
    std::cout << rand() << std::endl;
    std::cout << rand() << std::endl;
    return 0;
}


// 프로그램 실행 결과 (1회차)
25861
357
11478
16

// 프로그램 실행 결과 (2회차)
25861
357
11478
16

// 프로그램 실행 결과 (3회차)
25861
357
11478
16

\(\texttt{srand()}\) Function (\(\texttt{srand()}\) 함수)

- Prototype : \(\texttt{void srand (unsigned int seed);}\)
- C++의 \(\texttt{<cstdlib>}\) 헤더파일에 정의되어 있다.
- \(\texttt{rand()}\) 함수가 난수를 생성할 때 사용할 Seed값을 제공하는 역할을 한다.
- \(\texttt{rand()}\) 함수는 \(\texttt{srand()}\) 함수의 매개변수로 들어온 Seed값과 매칭되는 숫자(=난수)를 리턴한다.
- 특정 Seed값에 대한 \(\texttt{rand()}\) 함숫값이 정해져 있으므로, 실행시간동안 매번 변하는 난수를 생성하고자 한다면, Seed로 오는 값이 계속해서 변하는 수(현재 시각값) 이어야 한다.

// Ex. srand() 함수 사용 예시

#include <iostream>
#include <cstdlib>

int main(){
    std::cout << rand() << std::endl;
    std::cout << rand() << std::endl << std::endl;
    
    srand(1234);
    std::cout << rand() << std::endl;
    srand(1234);
    std::cout << rand() << std::endl;
    srand(13579);
    std::cout << rand() << std::endl;
    
    return 0;
}


// 프로그램 실행 결과 (1회차)
19748
26750

30181
30181
7287

// 프로그램 실행 결과 (2회차)
19748
26750

30181
30181
7287

// 프로그램 실행 결과 (3회차)
19748
26750

30181
30181
7287

// srand() 함수를 사용해도, Seed값이 매번 변하지 않으면
// 프로그램을 몇 번이고 실행해도 리턴하는 난수값은 이전과 동일하다.

\(\texttt{time()}\) Function (\(\texttt{time()}\) 함수)

- Prototype : \(\texttt{time_t time (time_t* timer);}\)
- C++의 \(\texttt{<ctime>}\) 헤더파일에 정의되어 있다.
- UCT기준 1970년 1월 1일 00시 00분 00초부터 경과된 시간을 초 단위로 리턴한다.
- 매개변수로 받는 \(\texttt{timer}\)는 결과값을 저장할 주소로, 매개변수를 \(\texttt{NULL}\)로 지정할 경우, 결과값을 따로 저장하지 않는다. (시간값 출력은 정상적으로 수행한다.)
- 시간을 얻을 수 없는 경우에는 -1을 리턴한다.
- \(\texttt{time_t}\) 데이터형은 \(\texttt{<ctime>}\) 헤더파일내에 \(\texttt{typedef}\) 키워드를 통해 재정의된 산술형 데이터형이다.
- 64bit 시스템의 경우 \(\texttt{time_t}\)는 \(\texttt{long long}\)형으로 정의되어 있다.
- 특정 포인터에 결과값을 저장하고 싶다면, 64비트 시스템에선 \(\texttt{long long}\)형 포인터를 매개변수로 전달해야 한다.

// Ex. time() 함수 사용 예시

#include <iostream>
#include <cstdlib>
#include <ctime>

int main(){
    srand(unsigned int(time(NULL)));
    
    std::cout << rand() << std::endl;
    std::cout << rand() << std::endl;
    std::cout << rand() << std::endl;
    
    // 난수의 범위를 한정하고자 하는 경우
    std::cout << rand() % 1000 << std::endl;      // 0 ~ 999 사이의 난수만 출력된다.
    std::cout << (rand() % 500) + 30;             // 30 ~ 529 사이의 난수만 출력된다.
    
    return 0;
}


// 프로그램 실행 결과 (1회차)
25255
11160
746
935
38

// 프로그램 실행 결과 (2회차)
25451
704
24020
942
320

// 프로그램 실행 결과 (3회차)
25490
31381
9014
557
291


  - \(\texttt{srand()}\) 함수의 매개변수로 \(\texttt{time()}\) 함숫값을 명시적으로 \(\texttt{unsigned int}\)형으로 변환하고 있는데, 이 방법 보다는 \(\texttt{static_cast}\)와 같은 캐스팅 연산자를 통한 형변환이 권고된다. (참조)