반응형

배경

프로그래밍을 배우다 보면 난수(Random Number)를 생성해야 하는 경우가 종종 생깁니다.
대표적인 예로는 확률과 관련된 것들이 있습니다.

  • 게임의 아이템 드랍율
  • 예측이 불가능한 일회용 값
  • 등등..

실제로 품질이 좋은 난수를 생성하는 것은 매우 힘든 작업이지만,
여기서는 C언어에서 간단하게 난수를 발생시키는 방법에 대해서 설명합니다.

rand 함수

C언어에서 간단하게 난수를 생성할 수 있는 방법은 rand 함수를 사용하는 것입니다.
rand 함수를 사용하기 위해서는 stdlib.h 헤더파일을 포함해야 합니다.
다음은 rand 함수를 사용하여 난수를 생성하는 예시코드 입니다.

#include<stdio.h>
#include<stdlib.h> // rand 함수를 포함하는 헤더파일

int main(void)
{
    int i = 0;
    printf("rand() 함수를 사용하여 10개의 난수를 생성 \n");

    for(i=0 ; i<10 ; i++)
        printf("%d\n", rand()); // 난수생성

    return 0;
}

실행 결과는 다음과 같습니다.

root@goorm:/workspace/coding_test# gcc /workspace/coding_test/std/std.c -o /tmp/a.out && /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
1804289383
846930886
1681692777
1714636915
1957747793
424238335
719885386
1649760492
596516649
1189641421
root@goorm:/workspace/coding_test# gcc /workspace/coding_test/std/std.c -o /tmp/a.out && /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
1804289383
846930886
1681692777
1714636915
1957747793
424238335
719885386
1649760492
596516649
1189641421

의도한대로 난수 10개가 정상적으로 생성되었습니다.

난수 생성 결과에 대한 이야기 1

눈치가 빠른분들은 여기서 궁금한것이 생길것입니다.

1. 왜 여러번 실행시 생성되는 난수가 똑같은 것인가?

C언어로 짜여진 프로그램을 실행하기 위해서는 컴파일을 해야합니다 (위의 gcc 명령어에 해당됩니다)
컴파일 되는 순간 난수의 값이 정해지며, 우리는 단순히 그것을 여러번 실행한 것 뿐입니다.

2. 그렇다면 생성되는 난수의 범위는 어디까지인가?

난수의 생성 범위는 0~n 까지이고 이 n의 값은 실행되는 환경에 따라 다릅니다.
헤더파일을 열어보면 RAND_MAX 라는 값이 있는데, 이 값이 난수의 최대값 n 입니다.

더 자세한 내용은 레퍼런스 사이트 를 참고해주세요.

SEED 값

위의 1번 궁금증을 해결하기 위하여 등장하는 개념이 seed 값입니다.
서로 다른 씨앗에서 서로 다른 식물이 자라듯이,
서로 다른 seed 값에서 서로 다른 난수가 생성됩니다.
이 seed 값을 설정하는 함수가 srand 함수입니다.

srand 함수

srand 함수 또한 stdlib.h 에 포함되어있습니다.
다음은 srand 함수를 사용하여 다른 seed 값으로부터 다른 난수를 생성하는 코드입니다.

#include<stdio.h>
#include<stdlib.h> // rand 함수를 포함하는 헤더파일

int main(void)
{
    int i = 0;
    printf("rand() 함수를 사용하여 10개의 난수를 생성 \n");

    srand(100); // 시드값 100 설정
    printf("seed값 100\n");
    for(i=0 ; i<10 ; i++)
        printf("%d\n", rand()); // 난수생성

    srand(200); // 시드값 200 설정
    printf("seed값 200\n");
    for(i=0 ; i<10 ; i++)
        printf("%d\n", rand()); // 난수생성

    return 0;
}

실행 결과는 다음과 같습니다.

root@goorm:/workspace/coding_test# gcc /workspace/coding_test/std/std.c -o /tmp/a.out && /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
seed값 100
677741240
611911301
516687479
1039653884
807009856
115325623
1224653905
2083069270
1106860981
922406371
seed값 200
331330603
197953680
10832164
2138423562
597828153
1365076974
372218870
1014115694
1211964559
854812119

난수 생성 결과에 대한 이야기 2

seed 값을 다르게 주면 다른 난수가 생성되는 것을 확인 할 수 있습니다.
이제 한발 더 나아가서, 실행할 때 마다 계속 다른 난수가 생성되게 하려면 어떻게 해야 할까요?
우리는 프로그램 실행시마다 자동으로 계속 바뀌는 값을 찾아야 합니다.
여기서 time 함수가 등장합니다

time 함수

time 함수는 1970년 1월 1일 이후 경과된 시간을 초 단위로 반환하는 함수 입니다. 반환되는 값을 다른말로는 timestamp 라고도 합니다.
time 함수를 사용하기 위해서는 time.h 헤더파일을 추가하여아 합니다.
다음은 time 함수를 추가하여 개선된 코드입니다.

#include<stdio.h>
#include<stdlib.h> // rand 함수를 포함하는 헤더파일
#include<time.h> // time 함수를 포함하는 헤더파일

int main(void)
{
    int i = 0;
    printf("rand() 함수를 사용하여 10개의 난수를 생성 \n");

    srand(time(NULL)); // 시드값으로 프로그램 실행 타임스탬프를 준다
    for(i=0 ; i<10 ; i++)
        printf("%d\n", rand()); // 난수생성

    return 0;
}

실행 결과는 다음과 같습니다

root@goorm:/workspace/coding_test# gcc /workspace/coding_test/std/std.c -o /tmp/a.out && /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
907292540
578206868
472556768
40734183
1512178519
246371126
1736140850
90178493
813094445
108308780
root@goorm:/workspace/coding_test# /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
127932628
542285782
2060952561
356635060
596058072
1288822579
1252399434
832774292
574918316
2051655844
root@goorm:/workspace/coding_test# /tmp/a.out
rand() 함수를 사용하여 10개의 난수를 생성
601099145
1246918761
147030223
1740858597
1391684167
98235141
1740602094
2106403234
822883800
1355317958

드디어 실행할 때 마다 난수의 값이 바뀌는 것을 확인할 수 있습니다.

난수 생성 결과에 대한 이야기 3

그렇다면 이 난수를 실제로 활용하려면 어떻게 해야할까요?
C언어 연산자 중 % 연산자를 활용 하는 방법이 있습니다.
% 연산자는 나눗셈을 수행한 뒤 나머지만을 남기는 연산자입니다.

예를들어 주사위를 구현한다고 하면,
rand() % 6 --> 0~5 의 값
(rand() % 6) + 1 --> 1~6 의 값 (참고로 % 연산자는 + 연산자보다 우선순위가 앞서기 때문에 괄호를 쓰지 않아도 정상적으로 동작합니다)
이런 식으로 %와 +를 활용하여 다양한 랜덤값을 구할 수 있습니다.

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기