[#9] rand, srand, #include <time.h>로 무작위 숫자 뽑기

9강에서는 rand에 대해 알아보겠습니다. 원래는 switch와 게임 만들기까지 함께 다루려고했는데,

rand자체를 설명하는데도 꽤 많은 양이 나와서 switch와 게임 만들기는 10강으로 넘겼습니다.

 


 

🔶 rand()

 

프로그래밍에서 무작위 숫자가 필요할 땐 rand()라는 함수를 씁니다.
예를 들어 컴퓨터가 숫자 하나를 골라놓고 "내가 뭘 골랐는지 맞춰봐~" 하는 게임을 만들려면
그 숫자를 사람이 아니라 컴퓨터가 알아서 정하게 해야만 합니다.

이 때 그 역할을 해주는 게 rand()입니다.

 

먼저 아래의 코드를 입력해 봅시다.

int num = rand();

이는 num이라는 변수에 무작위 값을 매기는 코드입니다.

다만 이렇게만 띡 하고 끝내버리면 숫자가 너무 커지게 됩니다.

그래서 설정해야 할 숫자 범위만을 뽑아내기 위해 % 연산자를 써야합니다.

 

 

🔹 % 연산자

 

% 연산자rand() 가 만든 큰 숫자 중에서 내가 원하는 범위만큼을 잘라내는 도구 역할을 합니다.

그냥 rand()만 썼을 땐 숫자가 너무 크고 범위도 너무 넓기 때문에, 실제 내가 제어할 범위를 설정해 줘야합니다.

이 때 % 연산자를 써서 원하는 범위를 설정할 수 있습니다.

 

위의 코드에서 % 연산자를 넣고 그 뒤에 숫자를 적게되면 범위가 설정되죠

int num = rand() % 10;  // 0~9 사이 숫자만 남김

코드를 이렇게 적었다면 딱 10개까지만 연산하게 됩니다.

C++ 1이 아닌 0부터 시작하기 때문에 10을 입력하면 1~10이 아닌 0~9가 됩니다.

만약 이걸 1~10으로 바꾸고 싶다면 10 뒤에 +1을 해주면 됩니다.

 

여러가지 예시를 표로 만들어서 더 잘 이해해봅시다.

코드 결과 범위
rand() % 2 0 또는 1 (두 가지 경우)
rand() % 3 0, 1, 2 (세 가지 경우)
rand() % 100 0 ~ 99 (100가지 경우)
rand() % 100 + 1 1 ~ 100 (시작점 조정까지 포함)

 

 

🔹 rand()는 랜덤이 아니다?

 

다시 rand()로 돌아와서 이어가겠습니다.

사실 rand()는 완전히 랜덤이 아닙니다.
그래서 막상 써보면 항상 비슷한 패턴으로 숫자를 만들어내죠.

 

for문을 이용한 코드를 통해 테스트를 해보겠습니다.

printf("난수 초기화 이전\n\n");
for (int i = 0; i < 10; i++)
{
    printf("%d", rand() % 10);
}
  • printf를 통해 가장 먼저 "난수 초기화 이전"을 표시해 줬습니다.
  • 이후 for문을 이용해 i = 0이고 i < 10일 경우 i++을 해줬습니다.
  • 그리고 rand()값을 % 10 줬으니, 0~9까지 총 10개의 난수가 출력될 겁니다.

자 이 코드를 적어놓고 한 번 출력해봅시다. 위처럼 숫자 10개가 랜덤하게 뜰 겁니다.

여기까지만 보면 "어? 랜덤으로 나오는거 같은데?"라고 생각할 수 있지만, 껐다가 한 번 더 실행을 해봅시다.

그럼 분명 실행했던 수와 완전히 똑같은 값이 다시 출력되는걸 알 수 있습니다.

 

몇 번을 다시해봐도 이 수는 항상 똑같이 나옵니다. 즉 '무작위(랜덤) 상태가 아니다'라는 거죠.

왜 그럴까요?

 

그 이유는 우리의 생각과는 다르게 컴퓨터는 스스로 무작위성을 만들 수 없기 때문입니다.
그래서 rand()는 정해진 알고리즘을 기반으로 "그럴듯한 숫자"를 만들어냅니다.
이걸 우리는 의사 난수(Pseudo-Random Number)라고 부르는데, 지금 굳이 이 용어까지 알 필요는 없습니다.

 

즉, 아무 설정 없이 rand()만 계속 쓰면 매번 실행할 때마다 비슷한 숫자들이 반복되게 됩니다.

그래서 우리는 다른 방법을 찾아야 합니다.

 

 

🔹 srand()와 time(NULL)

 

위의 문제점을 해결하기 위해 등장하는 것이 바로 srand()time(NULL)입니다.

 

srand()rand()의 시작점을 바꿔주는 함수입니다. 이걸 "랜덤 시드(seed)를 심는다"라고 표현합니다. (seed + random)

프로그래밍에서 ‘시드’랜덤 숫자를 만들어내는 출발점이 되는 숫자를 말합니다.

 

다만 이 srand()를 쓰려면 time(NULL)이라는 한가지 함수를 추가해줘야 합니다.

time(NULL)은 현재 시간을 초 단위로 반환하는 함수입니다.

 

즉 1초마다 값이 바뀌고, 그걸 시드로 주면, 실행할 때마다 완전히 다른 난수 패턴이 나오는 것이죠.

또한 이 time(NULL)을 쓰기 위해서는 #include <time.h>가 꼭 필요합니다.

이 라이브러리는 우리가 맨 위에 입력했던 #include <stdio.h> 밑에 붙여넣으면 됩니다.

혹시 저걸 붙였는데도 정상적으로 코드 실행이 안된다면 밑에 #include <stdlib.h>도 추가해주세요

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

 

 

 

🔹 #include <time.h>는 왜 필요한가

C 언어에는 기본적으로 시간과 관련된 기능이 없습니다.

그래서 time()이나 time_t, NULL, clock() 같은 시간 관련 기능을 쓰려면
시간 관련 라이브러리인 <time.h>를 포함해야 합니다.

 

만약 이를 안 넣고 time(NULL)을 쓸 시에는 컴파일 에러가 납니다.

 

그럼 이제 원리는 다 알았으니 srand()를 이용해 난수를 초기화시키는 코드를 만들어봅시다.

코드 작성은 위와 거의 동일하지만, 여기에 rand()에 srand(time(NULL))도 추가로 넣어줄 겁니다.

printf("난수 초기화 이후\n\n");
srand(time(NULL));
for (int i = 0; i < 10; i++)
{
    printf("%d", rand() % 10);
}

자 최종적으로 코드가 이렇게 바꼈습니다. for문 위에 srand(time(NULL))을 넣어줬죠.

이제 실행을 해 보면 아까와는 다르게 매번 숫자가 바뀌는 것을 확인할 수 있습니다.