c++ 랜덤 숫자 생성하기 / 컴퓨터 난수 시드 설정



랜덤 넘버를 설정 할려면 cstdlib 이라는 라이버리를 선언하고
rand()이라는 함수를 선언하면 된다.

#include <iostream>
#include <cstdlib>

int main(){

for(int i=0; i<5;i++){
std::cout << rand() << std::endl;
}

return 0;
}



하지만 계속 실행할때마다 같은 값이 나오게 된다.
난수는 생성했지만 그 난수가 실행할때마다 바뀌어야 하는데 계속 똑같은 값이 나오다니..

그래서 rand함수는 seed라는것을 설정을 해줘야한다

근데 seed가 또 뭐냐?


생각 외로 컴퓨터는 난수를 간단히 만들 수 없다.
컴퓨터는 기본적으로 정해진 입력에 따라 정해진 값을 낼 뿐이다.
컴퓨터는 무의시기이 없기 때문이기땜에, 랜덤한 값을 초래 할 수가 없다.

난수표를 쓰는데 난수표가 정해진 이상 결국 같은 순서로 같은 숫자가 나오게 된다.

이를 해결하기 위해 난수표를 여러개 만들어 놓고
매번 다른 난수표를 읽도록 만드는 것이다.
이 난수표를 선택하는 것을 시드라고 표현한다.

그런데 시드값이 똑같으면 선택되는 난수표도 똑같기 때문에
시드값도 바뀌어야한다.

그럼 딜레마다

난수를 만들려면 난수가 필요하다니! 

그래서 보통 시드값으로 현재 시간을 넣어서 해결한다. (ms) 기준으로

그래서 시드를 기반으로 한 랜덤 함수는 왕ㄴ전한 무작위라고 보기가 힘들다.
특정 패턴의 경우 영원히 안나올수도 있다.


그래서 rand 함수는 시드라는 값에 의해 생성되므로 시드 값을 설정을 해주지 않아
같은 시드값으로 실행외 되어 위와같은 현상이 나타난다
이를 해결하기 위해서 srand 함수를 이용하여 시드값을 설정해주어야한다.

srand는 호출할때 전달받는 인자를 기반으로 해서 난수를 초기화 시켜준다
rand는 srand로 인해 생성된 값을 바탕으로 난수를 생성해줍니다
time 함수는 인자값으로 null을 넘기면 1970년 1월 1일 0시 이후부터 인자값까지 현재까지 흐른 초 수를 리턴해줍니다.


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

using namespace std;

int main(){

     srand(time(NULL));
    for(int i=0;i<10;i++){
         cout << rand() << endl;
    }

}

위 예저처럼 stand(time(NULL));
코드 한줄을 rand 함수 호출 전에 선언하면 시간을 기준으로 초기화 되는 진정한 난수를
만들어 낼수 있게 된다.

그러면 중복 없는 난수가 생성이 가능하다.


+ 랜덤한 수를 생성하는 방법

랜던한 값은 아무 값이다
0 부터 999999... 까지의 숫자 말고,
우리가 1~10까지의 랜덤한 값만 원한다면 어떻게 해야 할까?

'%' 을 이용하는 겁니다

%는 어떤 수를 나누었을때의 나머지를 얻을때 사용하는 연산자이다.
10%3 의 결과는 1 입니다
몫이 3 이고 나머지는 1이다.

0~10까지의 범위내의 랜덤한 값을 얻고 싶다고 할때, 어마어마하게 큰 수를 10으로 나누면
그 나머지가 0~9 사이의 값이 나온다.



999999999990%1 -> 0
999999999999%2 -> 1
999999999999%3 -> 2

...

999999999999%n10->9

이렇게 0~9 까지의 수만 나온다
이 모든값이 +1 만 해주면 우리가 원하는1~10 사이의 랜덤값을 얻을수 있습니다.


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


void set_random_seed(){ 

     std::srand(std::time(0));

}

int randn(int n){

     return std::rand() % n;

}


이 함수는
0~n-1까지의 범위의 랜덤값을 얻었다



1. time을 seed로 가지고 있는 srand함수를 부르고
2. rand() 함수를 이용해서 approx. 완벽한 랜덤값을 가조오고
3. 랜덤한 값을 %n 으로 나머지를 구해서 0~n-1 까지의 범위의 랜덤값을 얻는다



댓글

이 블로그의 인기 게시물

(오라클) View(뷰) + where/order by/like/is/() / in 사용방법 예제

(오라클) Sequence/시퀸스의 활용과 개념