카테고리 없음

#OOP&rand() 함수의 작동

마쿠어 2024. 3. 24. 01:51

C++ 표준 라이브러리에 속해 있는 가장 쉽게 사용할 수 있는 랜덤 함수는 기본적으로 rand() 와 srand()으로 구성되어 있다.

 

#include <iostream>
#include <cstdlib>
using namespace std;

int main(){
    srand(1);

    for(int i=0; i<15; i++){
        cout << rand() << endl;
    }

    return 0;
}

 

가장 간단한 예시로 이러한 함수의 경우, 결과 값으로는 아래와 같은 값을 가지게 된다.

위 함수에서 rand()함수의 기본적인 구성을 알아보자.

 

먼저, 랜덤함수는 '시드'를 기준으로 c++라이브러리에 정해져있는 일정한 연산을 거쳐서 순서대로 난수를 뱉어내는 역할을 한다. 이 때, 시드는 srand( ) 함수를 통해서 넣게 되고, 난수를 뱉어내는 것은 rand()을 통해서 하게 된다.

단순히 보면 랜덤한 값을 뱉는다고 보이지만, 실제로는 정해진 연산에 의해서 시드가 동일한 경우 항상 같은 순서로 값을 뱉는 함수이다. 즉 위의 함수는 언제나 같은 값을 출력하는 것이다.

 

그렇다면 시드를 2로 바꾼다면 어떻게 될까?

이 경우는 시드가 2인 경우를 기준으로 난수 값을 뱉어내는 것이다. 즉, rand()함수는 따지고 보면 진짜로 무작위 값을 뱉는 것이 아니다. 따라서 이 경우는 c++ 라이브러리에 속한 또 하나의 함수 time()을 활용한다. srand(time(NULL))을 활용하여, 조금 더 랜덤한 값을 뱉고자 한다. (time(NULL)은 현재 시간을 초로 환산한다. 즉 시간에 기반한 난수 값을 출력할 수 있다.)

 

 

 

기본적인 이해는 이정도이다. 하지만 한 가지 중요한 것은 과연 rand()함수는 어디에서 작동을 할까? 이다. 아래의 코드에서는 과연 객체 a와 b에서 각기 다른 시드로 작동을 할까?

 

#include <iostream>
#include <cstdlib>
using namespace std;

class test{
    public:
    test(int a);
    int print();
};
int test::print(){
    int num = rand();
    return num;
}
test::test(int a){
    srand(a);
}

int main() {
    test a(1),b(2);
    int i;
    srand(3); // 시드 값을 1로 설정
    for( i = 0; i < 5; ++i) {
        std::cout << rand() << ' '; // rand() 함수 호출하여 난수 출력
    }
    cout << endl;
    for( i =0; i< 5; i++){
        cout << a.print() << ' ';
    }
    cout << endl;

    for( i=0; i<5; i++){
        cout << b.print() << ' ';
    }
    cout << endl;
}

결과를 본다면, 3줄 모두 시드 1을 기반으로 출력이 됨을 알 수 있다. 분명히 객체 a와 b에서 각기 다르게 시드를 설정한거 같지만, 결과적으로는 시드 3을 기반으로 출력이 되었다.

이유는 rand()함수는 전역 함수이기 때문이다. srand()가 어디에서 호출이 되었던 간에, 이 영향은 global하게 영향을 미치게 되고, 위의 코드에서는 메인 함수에서 호출한 srand(3)이 가장 마지막 호출이기에 시드가 3으로 작동한 것이다.

 

아래 draft C99 standard의 내용을 보면 기본적인 작동 원리를 알 수 있다.

 


The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned 
by subsequent calls to rand
. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

 

 

추가로.... 시드가 바뀌면 난수의 순서도 다시 초기화 된다.

srand(1)

rand() rand() rand() // 3번째 난수까지

srand(2)

rand() rand() // 시드가 2인 경우의 2번째 난수

srand(1)

rand() // 시드가 1인 경우 첫번째 난수