C 언어에서 난수를 만들려면 rand() 함수를 이용합니다. rand()는 0 부터 RAND_MAX 사이의 난수를 생성합니다. 32bit 리눅스 시스템에서 RAND_MAX값은 2147483647입니다. 즉, int 변수값의 양의 값 최대값입니다.

난수 생성에는 rand()

일단 예제를 보시겠습니다.

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

int main( void)
{ 
   int   ndx;   
        
   printf( "RAND_MAX = %dn", RAND_MAX);

   for ( ndx = 0; ndx < 5; ndx++)
   {
      printf( "%d %dn", ndx, rand());
   }        

   return 0;
}

실행하면 아래와 같습니다.

]$ ./ss
RAND_MAX = 2147483647
0 1804289383
1 846930886
2 1681692777
3 1714636915
4 1957747793
]$

0에서 int 변수 값중 가장 큰 양의 값을 가지므로 원하는 범위의 값을 구하기 위해서는 나머지 이용합니다. 즉, 1부터 100 사이의 난수를 구하려면,

printf( "%d %dn", ndx, rand() % 100 +1);

그러나 문제가 있습니다. rand()는 난수를 만들지만 실행할 때 마다 같은 난수를 같은 순서로 만들어 낸다는 점입니다.

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

int main( void)
{ 
   int   ndx;   
        
   for ( ndx = 0; ndx < 5; ndx++)
      printf( "%d %dn", ndx, rand() % 100 +1);

   return 0;
}

이 프로그램을 연속으로 실행 시켜 보겠습니다.

]$ ./a.out
0 84
1 87
2 78
3 16
4 94
]$ ./a.out
0 84
1 87
2 78
3 16
4 94
]$

실행할 때마다 같은 난수가 같은 순서로 생성됩니다. 그러므로 실행할 때 마다 새로운 난수를 생성할 수 있도록 난수를 생성하는 기초값, 즉 seed 값을 바꾸어 주어야 합니다. 난수의 seed는 srand()를 사용하여 변경할 수 있습니다.

난수 생성을 위한 seed 지정 srand()

그러나 같은 seed 값을 사용한다면 어떻게 될까요?

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

int main( void)
{ 
   int   ndx;   

   srand( 99);
   for ( ndx = 0; ndx < 5; ndx++)
      printf( "%d %dn", ndx, rand() % 100 +1);

   return 0;
}
]$ ./a.out
0 73
1 25
2 50
3 14
4 70
]$ ./a.out
0 73
1 25
2 50
3 14
4 70
]$

아까와는 다른 난수이지만 역시 실행할 때 마다 같은 난수가 같은 순서로 생성됩니다. 그러므로 실행할 때 마다 난수의 seed 값을 매번 다른 값으로 지정해 주어야 합니다.

이 seed 값으로 사용하는 것이 시간입니다. time.h 에 선언된 timc() 함수는 초단위의 현재 시간값을 받습니다. 해서 아래 처럼 프로그램을 바꾸었습니다.

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

int main( void)
{
   int   ndx;

   srand( time( NULL));
   for ( ndx = 0; ndx < 5; ndx++)
      printf( "%d %dn", ndx, rand() %100 +1);

   return 0;
}

실행하면 실행할 때 마다 새로운 난수가 생성되는 것을 보실 수 있습니다.

]$ ./a.out
0 23
1 3
2 40
3 17
4 81
]$ ./a.out
0 71
1 31
2 1
3 88
4 91
]$

참고로 약간 병적인(?) 얘기를 하겠습니다. 이 프로그램을 빠르게 실행하면 아래와 같이 같은 난수가 출력될 수 있습니다.

]$ ./a.out
0 65
1 79
2 4
3 7
4 15
]$ ./a.out
0 65
1 79
2 4
3 7
4 15
]$

왜 일까요? srand() 에 time()까지 사용했는데 이렇게 난수가 중복되는 경우가 생겼을 까요? 그것은 time()이 초 단위이기 때문입니다. srand()는 프로그램 시작 시에 한 번 사용하면 되기 때문에 1초 이내에, 더 정확히 말씀 드려서 같은 초 시간에 연속으로 실행되면 이와 같이 난수가 중복될 수 있습니다.

그러나 이런 경우는 극히 드물겠죠. 드물더라도 이런 경우가 없다고 보장할 수 없다고 생각하고 깨름직하다면 getpid()를 사용하시면 됩니다. getpid()는 현재 실행 중인 프로세스의 아이디를 구해줍니다. 같은 프로그램을 실행해도 실행할 때 마다 프로세스 아이디는 증가되기 때문에 매번 다른 값을 반환하게 됩니다.

그러나 이 프로세스 아이디를 사용하기에는 무리가 있습니다. 왜냐하면 시스템이 리부팅이 되면 프로세스 아이디는 초기화가 되기 때문이죠. 이런 이유로 time()함수값과 같이 사용합니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>    // time()
#include <unistd.h>  // getpid()
int main( void)
{
   int   ndx;

   srand( (unsigned)time(NULL)+(unsigned)getpid());
   for ( ndx = 0; ndx < 5; ndx++)
      printf( "%d %dn", ndx, rand() %100 +1);

   return 0;
}

태그 : *gcc *C언어