C++에서는 <ctime>헤더에 포함된 time 함수를 제공한다. time 함수의 원형은 다음과 같다
time_t time(time_t *pTime)
여기서 time_t는 시간을 나타내기 위해 만들어진 데이터 타입인데 __int64와 같다.
typedef __time64_t time_t;
typedef __int64 __time64_t;
time 함수는 1970년 1월 1일을 기준으로 1초씩 증가해서 함수 호출 당시에는 몇초가 지났는지를 반환해준다.
사용법은 아래와 같이 두가지가 있다.
time_t t1 = time(nullptr); //방법 1, nullptr 대신 0을 줘도 무관
time_t t2;
time(&t2); // 방법 2
time 함수의 기능이 1970년 1월 1일을 기준으로 1초씩 증가한다고 했다. 이 말은 매번 time 함수가 포함된 프로그램을 실행할 때 마다 값이 다르다는 의미다(물론 1초에 여러번 실행하는 걸 제외하고). 이 특징을 이용할 수 있는 곳이 있는데 바로 난수를 만들때이다.
가장 기본적인 난수발생 함수는 rand()이다. 하지만 rand 함수는 완벽한 난수를 만들어내지 못한다 예를 들어서
int main()
{
std::cout << rand() << std::endl;
std::cout << rand() << std::endl;
std::cout << rand() << std::endl;
return 0;
}
이 코드를 여러번 실행하면 매번 같은 값이 나오는 것을 확인할 수 있다. 이 말은 곧 rand 함수는 완전한 난수를 만들어내지 못하고 있다는 의미다. 사실 rand함수란 랜덤한 값을 포함하고 있는 표에서 난수를 가져오는 것인데 이 표를 바꾸지 않고 매번 같은 표에서 난수를 가져오기 때문에 위와 같은 현상이 일어나는 것이다.
이 때 완벽한 난수를 만들기 위해서 프로그램이 실행될 때 마다 다른 seed값을 줘야 하는데, 아까 배운 time 함수를 이용하면 매 초마다 다른 seed값을 만들어낼 수 있을 것이다. seed값을 주는 함수는 srand를 이용하면 된다. 함수 원형은 아래와 같다.
void srand (unsigned int seed)
srand함수와 time함수를 이용하면 완전한 난수를 만들어낼 수 있다.
int main()
{
srand(time(0));
rand(); // 가급적 사용하지 않기
// 난수 생성
std::cout << "random number: "<< rand() << std::endl;
return 0;
}
srand함수와 time함수를 사용해서 seed값을 전달한 바로 뒤 첫번째 rand는 완전한 난수가 아닌 듯 보인다. 사용해보면 일정한 값에서 조금씩 증가하기만 할 뿐 완전한 난수가 아니다. 그 이유는 stackoverflow에서 찾을 수 있었다.
해석해보면 seed값끼리 너무 가까워서 난수 발생기가 발산하기 까지 충분한 시간이 없기 때문에 라고 한다. 아마 seed값을 줄 때 마다 몇초씩 밖에 차이가 안나서 그런 것 같다. 각 실행의 seed값도 서로 차이가 크게 한다면 해결 이 문제도 해결할 수 있었다.
Reference
https://blockdmask.tistory.com/308
https://stackoverflow.com/questions/27301090/first-rand-generates-the-same-value-after-srandtime0