<개인공부>/[C언어, C++]

[C언어/C++] rand, srand, time 랜덤함수에 대해서 (난수생성)

BlockDMask 2019. 1. 11. 00:15
반응형

안녕하세요. BlockDMask 입니다.

오늘은 C/C++로 개발할때 가끔 사용하는 랜덤한 수(난수)를 생성하는 함수에 대해서 알아보겠습니다.

랜덤한 값을 가지고올때 필요한데요. 그럼 시작해보겠습니다.

1. rand 함수원형과 사용법

1) 헤더파일

-  C언어<stdlib.h> / C++ <cstdlib>


2) 함수원형

- int rand (void)


3) rand 함수가 하는일

: Generate random number [0 ~ RAND_MAX]

: 랜덤한 숫자를 반환합니다.

: 그 범위는 0~ RAND_MAX 까지인데요, RAND_MAX라는 것은 stdlib.h 헤더파일에 매크로로 작성되어있습니다.

: RAND_MAX = 32767

: 결국 rand() 함수가 반환하는 값은 0~32767 사이의 값 이라는 것입니다.


하지만, rand() 함수는 프로그램이 생성될때 딱 값이 정해지기 때문에 프로그램을 여러번 실행시켜도 동일한 값이 나옵니다.

확인해 볼까요?


4) rand() 함수 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//C언어만 사용하시는 분들은 해당 헤더만 포함하세요.
//#include<stdio.h> 
//#include<stdlib.h>
//#include<time.h>
 
//C++용 헤더
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
 
int main(void)
{
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
    system("pause");
    return 0;
}
cs


5) 결과1,2

: 보시는 바와같이 프로그램을 아무리 많이 실행시켜도 동일한 숫자가 나오게 됩니다.

: 아니이게 무슨 랜덤함수입니까!!!!!!!!!!!!!!!!!!!!!!!

: 그럼 srand는 뭐가 다른가?? 궁금하시죠? 아래쪽으로 내려가 보시죠.


2. srand 함수원형과 사용법

1) 헤더파일

- C언어<stdlib.h> / C++ <cstdlib>


2) 함수원형

- void srand (unsigned int seed)


3) srand 함수가 하는일

: Initialize random number generator.

: rand 함수에 사용될 수를 초기화 하는일인데요, 이 초기화를 매개변수로 받는 seed 값을 이용해서 합니다.

: rand 함수는 내부적으로 어떤 srand의 매개변수로 들어온 seed 값과 매칭되는 숫자가 정해집니다. 그래서 seed 값에 의해서 rand 함수의 결과값이 변할 수 있습니다.


4) 그럼 seed 값을 이용해서 rand() 값을 초기화 해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//C언어만 사용하시는 분들은 해당 헤더만 포함하세요.
//#include<stdio.h> 
//#include<stdlib.h>
//#include<time.h>
 
//C++용 헤더
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
 
int main(void)
{
    printf("1. rand()\n");
    printf("rand : %d\n", rand());
    printf("rand : %d\n", rand());
 
    printf("2. rand()와 동일한 시드의 srand()\n");
    srand(32323);
    printf("rand : %d\n", rand());
    srand(32323);
    printf("rand : %d\n", rand());
    srand(32323);
    printf("rand : %d\n", rand());
 
    printf("3. rand()와 4개의 시드 srand()\n");
    for (int i = 0; i < 4++i)
    {
        srand(i);
        printf("rand : %d\n", rand());
 
    }
    system("pause");
    return 0;
}
cs


5) 결과

: 혹시 뭔가 이상하지 않나요? srand의 seed값이 일정한것이 들어갔을때 일정한 rand 값이 나오지 않나요? 

: 이게 무슨 랜덤함수입니까!!!! 반만 랜덤이지!!!!!!!

: 이런식으로 초기화를 하면, 프로그램이 만들어질때 이미 어떤 seed에 대한 rand 값이 정해져 있기 때문에 동일한 seed 를 이용하면 우리가 원하는 '진짜' 랜덤 함수를 만들 수 없습니다. 그렇기 때문에 프로그램 실행중에(런타임동안) 항상 변하는 seed 값을 이용해서 srand를 해줄 필요가 있겠죠???

: 그래서 사람들이 '음.. 항상 변화하는 숫자가 없을까? 절대 이전에 들어온 값과 동일하지 않고?' 이런 생각을 하다가 아! 시간을 이용하면 되겠다 싶어서, 시간을 seed 값으로 넣는 것입니다. 그럼 아래쪽으로 내려가서 time 함수를 한번 볼까요?


: 아! time함수를 보러가기전에 stdlib.h에 선언되어있는 rand, srand, RAND_MAX을 한번 확인해 보고 가시죠.

이렇게 함수의 원형을 보는 것도 매우 중요합니다.


3. time 함수 원형과 사용법

1) 헤더파일

- C언어 <time.h> / C++ <ctime>


2) 함수원형

- time_t time (time_t* timer);


3) time 함수가 하는일

: UCT 기준 1970년 1월 1일 0시 0분 0초 부터 경과된 시간을 초(sec)로 반환하는 함수.

: 이렇게 초로만 반환을해서 연도, 월, 일, 시, 분, 초로 나타내기 위해서는 다른 작업이 필요하거나, 다른 함수를 이용해서 날짜를 얻어올 수 있지만, 우리가 지금 원하는 것은 시간이 아니라 항상 변화하는 숫자일 뿐 입니다.

: 그렇기 때문에 해당 포스팅에서는 time함수를 시간이 아닌 항상 변화하는 숫자로 만 사용하겠습니다.


4) time 함수 출력 값 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//C언어만 사용하시는 분들은 해당 헤더만 포함하세요.
//#include<stdio.h> 
//#include<stdlib.h>
//#include<time.h>
 
//C++용 헤더
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
 
int main(void)
{
    printf("%lld\n", time(NULL));
 
    system("pause");
    return 0;
}
cs


5) 결과


6) 어? time_t가 반환형인데 time_t가 뭘까? 궁금하시죠?

: 그럼 코드를 따라 가봅시다. 쭉쭉 코드를 따라가다 보면 이렇게 나옵니다.

: 이렇게 time_t는 32비트 컴퓨터인가 64비트 컴퓨터인가를 구분을 두어서 타입을 정의하고 있습니다.

: __time64_t는 마우스오버를 해보면 long long 타입임을 알 수 있습니다.


4. 랜덤함수 예제 (rand, srand, time 함수를 이용)

1) 랜덤한 수를 생성하는 방법

- 랜덤한 값은 아무 값이잖아요. 0~999999999999999999 까지의 숫자 말고, 우리가 1~10까지의 랜덤함 값만 원한다면 어떻게 해야할까요?

- 우리가 쓰는 방법은 "%"를 이용하는 겁니다. 네 맞습니다 %는 어떤 수를 나누었을때의 나머지를 얻을때 사용하는 연산자 입니다.

: 10 % 3의 결과는 1 입니다. 몫이 3이겠고 나머지는 1이니까요. 그렇다면 조금 생각을 바꿔볼까요? 

우리가 0~10 까지의 범위 내의 랜덤한 값을 얻고 싶다고 할때, 어마어마하게 큰 수를 10으로 나누면 그 나머지가 0~9 사이의 값이 나오겠죠? 딱 10개.! 아하! 이걸로 구하는 거구나!

: 4214142140 % 10 -> 0

: 4214142141 % 10 -> 1

: 4214142142 % 10 -> 2

: 4214142143 % 10 -> 3

: 4214142144 % 10 -> 4

: 4214142145 % 10 -> 5

: 4214142146 % 10 -> 6

: 4214142147 % 10 -> 7

: 4214142148 % 10 -> 8

: 4214142149 % 10 -> 9

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


그럼 우린 

첫번째로, time을 seed로 가지고있는 srand 함수를 부르고

두번째로, rand() 함수를 이용해서 매우 완벽한 랜덤한 값을 가지고 오고

세번째로, 그 랜덤한 값을 % n 으로 나머지를 구해서 0~n-1 까지의 범위의 랜덤값을 얻는 것 입니다.


2) 랜덤함수 구현 예제.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//C언어만 사용하시는 분들은 해당 헤더만 포함하세요.
//#include<stdio.h> 
//#include<stdlib.h>
//#include<time.h>
 
//C++용 헤더
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
 
int main(void)
{
    srand((unsigned int)time(NULL));
 
    for (int i = 0; i < 20++i)
    {
        int num = rand();
        printf("난수 : %d\t나머지 : %d\n", num, (int)num % 10);
    }
    system("pause");
    return 0;
}
cs

: C++유저 분들계서는 명시적 형변환시에 위예제에서같이 ( ) 괄호 말고 static_cast와 같은 캐스팅 연산자를 통해서 사용하시길 추천드립니다. 관련문서는 여기 있습니다.

[<개인공부>/[C언어 \ C++ 언어]] - [C++] static_cast (타입캐스트 연산자)

[<개인공부>/[C언어 \ C++ 언어]] - [C++] const_cast (타입 캐스트 연산자)

[<개인공부>/[C언어 \ C++ 언어]] - [C++] dynamic_cast (타입캐스트 연산자)


3) 결과.

: 와우! 이렇게 해서 랜덤함수, 랜덤함수를 구현하는 방법에 대해서 알아보았습니다. "참 쉽쥬?"


감사합니다. 하트 부탁드려요.

질문이 있으면 댓글 남겨주세요.

반응형