상세 컨텐츠

본문 제목

C/C++ 랜덤숫자, 난수 생성 함수 rand, srand 사용법 및 중복 없는 난수 생성 관련

본문

반응형

 

=================================

=================================

=================================

 

 

 

출처: http://wwwwwwwwwwwww.tistory.com/125

 

로또 당첨번호를 생성하기 위해 1부터 45사이의 난수 6개를 함수(rand)를 이용하여 출력

// 1부터 45사이의 정수 난수를 출력

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int i;
    for(i=1;i<=6;i++)
        printf("%d\n", rand()%45+1);
    return 0;
}

// 실행 결과

 

 

 

 

 

 

 

 

 




// 위의 프로그램을 두번 실행해 결과를 보면 첫번째와 두번째 실행결과가 같다.
    실행할 때마다 같은 난수가 아닌 서로다른 난수를 생성하기 위해서는 새로운 라이브러리 함수를 추가해야 한다.

// 난수 초기화를 이용하여 서로 다른 난수를 생성

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
    int i;
    srand(time(NULL));
    for(i=1;i<=6;i++)
        printf("%d\n", rand()%45+1);
    return 0;
}

// 실행 결과

 

 

 

 

 

 




// rand()를 이용하여 생성한 난수는 해당범위내의 숫자들에 대해서 나타날 확률이 모두 같기 때문에 한번의 실행에서
    중복되는 난수가 발생할 수 있다.

// 난수를 중복되지 않게 생성하는 방법
    로또 당첨번호 생성 프로그램

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
    int i, r, j, random[7];
    srand(time(NULL));
    for(i=0;i<=6;i++)
    {
        again:;
        r=rand()%45+1;
        for(j=0;j<=i-1;j++)
            if(r==random[j])
                goto again;
        random[i]=r;
    }
    for(i=0;i<=6;i++)
        printf("%d\n", random[i]);
    printf("\n");
    return 0;
}

// 실행 결과

 

 



출처: http://wwwwwwwwwwwww.tistory.com/125 [필기노트]

 

 

 

=================================

=================================

=================================

 

반응형

 

728x90

 

 

출처: http://blog.naver.com/PostView.nhn?blogId=xtelite&logNo=50023986643&viewDate=&currentPage=1&listtype=0

 

중복되지 않는 난수 생성은 C/C++ 표준함수가 지원해 주지 않습니다.

 

C++의 STL을 이용하면 가능하지만 아직 그것을 배우지 못했기 때문에 그 전까지는

 

난수를 생성하고 이미 같은 난수가 생성되었는지 일일이 체크해서 이미 존재하는 난수라면

 

존재하지 않는 난수를 만들 때까지 반복해서 난수를 생성하는 방법을 사용해야 합니다.

 

다음은 하나의 예입니다.

 

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

 

int main()

{

       int a[10];

       int i, j;

       int bFound;

 

       srand((unsigned int)time(NULL));

 

       for ( i = 0; i < 10; ++i )

       {

             while ( 1 )

             {

                    // 

난수를하나생성

                    a[i] = rand() % 10 + 1;

                    // 

이미있는값인지확인하기위해플래그설정

                    bFound = 0;

                    // 

같은값이있는지확인한다

                    for ( j = 0; j < i; ++j )

                    {

                           // 

같은값이있으면

                           if ( a[j] == a[i] )

                           {

                                 // 

같은값이이미있음

                                 bFound = 1;

                                 break;

                           }

                    }

                    // 같은값이없으면while

문탈출

                    if ( !bFound )

                           break;

             }

       }

 

       // 

결과출력

       for ( i = 0; i < 10; ++i )

             printf("%4d", a[i]);

       printf("\n\n");

 

 

       return 0;

}

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://shaeod.tistory.com/292

 

 

※요약

rand : 예측할 수 없는 하나의 난수를 생성한다.

난수의 범위는 0~RAND_MAX 까지이며 RAND_MAX는 0x7fff이므로 , 결국 난수의 범위는 0~32767 이다.

srand : rand 함수만으로 생성되는 난수는 일정한데 

srand를 이용, 시간 값을 매개로 초기화하면 일정하지 않고 불규칙적인 난수가 생성된다.

 

 

※함수 원형 및 설명

int rand( void );

 

void srand( unsigned int seed );

 

 

 

※사용법 ( 사용법 부분은 "C언어를 배우자" 카페의 라이터님의 게시물을 허락 후 옮겼습니다. )

1. 기본 사용법

i = rand()%n

이것은 0 ~ n-1 범위의 난수를 i에 대입합니다.

예를 들어 n=6 이라 하면 0, 1, 2, 3, 4, 5, 중 하나가 i에 대입되는 셈이지요.

 

2. 기본 응용

i = rand()%n + m

이것은 1번을 응용한 것으로, 0+m ~ n-1+m 범위의 난수를 i에 대입합니다.

예를 들어 n=6, m=4 라 하면 4, 5, 6, 7, 8, 9, 중 하나가 i에 대입되는 셈이지요.

다른 예로 n=5, m= -2 라 하면 -2, -1, 0, 1, 2 중 하나가 i에 대입되는 것이죠.

 

 

i = rand()%n * m

이것은 0 ~ n-1 으로 나올 수 있는 수에 m을 곱한 수를 i에 대입하는 식입니다.

예를 들어 n=4, m=2 이라 하면, 0, 2, 4, 6 중 하나가 i에 대입되는 것이죠.

m의 값을 2로 주면 2의 배수, 3을 주면 3의 배수가 나오는군요.

 

이제 두개를 섞어서,

 

i = (rand()%n + m) * o

이것은 0+m ~ n+m-1 으로 나올 수 있는 난수에 o을 곱한 수를 i에 대입하는 식입니다.

n = 3, m = 2, o = 4 라 하면, 8, 12, 16 중 하나가 i에 대입되는 것이죠.

이것도 어떤 수의 배수를 사용할 때 용이하겠습니다.

 

i = rand()%n * m + o

이건 0 ~ n-1 으로 나올 수 있는 수에 m을 곱하고, o를 더한 수를 i에 대입하는 식입니다.

n = 3, m = 2, o = 5 라 하면, 5, 7, 9 중 하나가 i에 대입되는 것이죠. 

 

3. 기본 심화 응용

i = rand()%n * m + o

이 식을 다시 한번 봅시다.

n의 값이야 0 이상으로 주고, m = 2, o = 0 으로 주면, 짝수가 생성됩니다.

m = 2, o = 1 으로 주면, 홀수가 생성되는것을 볼 수 있습니다.

 

 

4. 배열을 이용한 응용 - 1 기본 기법

배열을 이용한 응용이라...  rand() 의 마법을 보실 수 있겠군요.

int ar[MAX] = {원하는 원소 MAX개}; 라는 배열이 있다고 생각하고...

 

i = ar[rand()%MAX]

이 식은 상당히 유용합니다. 예를 들어보는게 제일 빠르겠지요.

MAX = 4로 잡고, ar 배열의 원소를 { 2, 5, 9, 3214324 } 이라 합시다.

저 4개의 숫자는 규칙성도 뭣도 없어서 위에서 본 응용법으로는 뽑아 낼 수가 없지요.

하지만 배열과 4번의 식을 이용한다면?

 

rand()%MAX 는 0 ~ MAX-1 범위의 수를 뽑아낼 것입니다.

MAX 가 4니까 0, 1, 2, 3, 이 나오겠지요? 그런 다음에 ar[rand()%MAX] 으로 ar배열 속에 있는 원소에 접근하는데...

rand()%MAX 가

0 이면 2

1 이면 5

2 이면 9

3 이면 3214324

를 i 에 대입할 수 있는거죠.

 

이렇게 배열을 이용하면 rand() 함수 한번의 호출로 불규칙한 수를 난수로 뽑아내 쓸 수 있는거죠.

응용법은... 아래쪽에 있습니다.

 

5. 배열을 이용한 응용 - 2 자세한 응용

이번엔 다른 배열 응용법을 알아봅시다.

 

복권을 만들었는데, 1/10 의 확률로 1등, 3/10의 확률로 2등, 6/10의 확률로 3등이라고 하고,

rand() 를 이용해 랜덤하게 추첨을 하려고 하는데..

 

" 3가지 경우가 있으니 rand()%3 해서 0 이면 1등, 1이면 2등... "

이런 생각은 떙 !!!!

0, 1, 2, 가 나올 확률은 같습니다!!!

 

" 그럼 rand()%10 해서 0 은 1등, 1~3 은 2등, 4~9 는 3등으로... 이런 복잡한 걸"

정답인데, 이러면 조건문이 들어가야 하는 복잡함이!!!!

 

배열 하나면 됩니다.

int ar[10] = { 1, 2, 2, 2, 3, 3, 3, 3, 3, 3 }

이런 배열 하나 준비 하시고!!!!

 

i = ar[rand()%10]

아하하하하하, 이러면 끝 !! i에는 추첨된 등수가 들어가게 됩니다.

설명해 드리죠.

 

rand()%10 으로 나올 수 있는 수는

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 이고, 이 10가지 수가 나올 수 있는 수학적 확률은 같습니다.

 

그러나, 0이 나올 확률은 1/10,

1, 2, 3 이 나올 학률은 3/10,

4, 5, 6, 7, 8, 9 가 나올 확률은 6/10  !!!

 

배열 원소를 보면, ar[0] 은 1이고

ar[1] ~ ar[3]은 2,   ar[4] ~ ar[9]는 3!!!!

 

배열로는 이런일이 가능합니다 !!!

※예제

 

아래는 중복 없는 난수 생성 예제입니다. 

로또 번호 생성 예제이며, 제가 배포하는 로또 프로그램에서 일부 가져와 군더더기를 제거하고  예제에 맞게 수정했습니다.

중복을 방지하기 위해 생성 여부에 대한 일종의 인덱스를 둬서 따로 검사하지 않아도 중복을 방지할 수 있게 했습니다.

흔히 사용하는 배열 요소를 처음부터 끝까지 조사 방식은 배열 개수에 따라 속도가 엄청 느려지므로 추천하지 않습니다.

이렇게 인덱스를 두는 방법은 에라토스테네스의 체를 구할 때도 이용되고 

데이터를 캐싱할 때 이미 불러들인 데이터인지 판별할 때도 사용됩니다.

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <stdlib.h>       //srand
#include <time.h>     //time
  
//#define _MAX 6
const int nMAX = 6;
  
void BubbleSort( int *nArr, int nArrSize );
  
int main( )
{
    //변수 생성 및 초기화 부분
    srand( (unsigned)time(NULL) );              //srand로 초기화
  
    int nLottoNum[nMAX] = { 0, };               //생성된 로또 번호를 저장할 변수
    bool bCheckExistOfNum[45] = { false, };     //생성된 번호가 중복인지 체크할 변수(인덱스)
  
    //번호 생성 부분
    for( int i=0 ; i<nMAX ; )                    //번호가 6개 생성될 때까지 돈다.
    {
        int nTemp = rand()%45;                  //0~44 범위의 번호를 생성한다.
  
        if( bCheckExistOfNum[nTemp] == false //중복 여부 판단
        {
            bCheckExistOfNum[nTemp] = true;     //번호가 중복 생성되지 않게 존재 여부를 true로 한다.
            nLottoNum[i] = nTemp+1;             //+1을 안해주면 범위가 0~44이다.
            ++i;                                //증감 연산을 for문에서 하지 않고 여기서 한다.
        }
    }
  
    //버블 정렬
    BubbleSort( nLottoNum, sizeof(nLottoNum)/sizeof(int) );
  
    //출력 부분
    for( int i=0 ; i<nMAX ; ++i )
    {
        printf( "%2d ", nLottoNum[i] );
    }
  
    return 0;
}
  
void BubbleSort( int *nArr, int nArrSize )
{
    for( int i=0 ; i<nArrSize-1 ; i++ )
    {
        for( int j=0 ; j<nArrSize-(i+1) ; j++ )
        {
            if( nArr[j] > nArr[j+1] )    //꺽쇠 방향으로 오름 차순, 내름 차순 결정
            {//값 교환 부분
                int temp = nArr[j];
                nArr[j] = nArr[j+1];
                nArr[j+1] = temp;
            }
        }
    }
}
 

 

=================================

=================================

=================================

 

 

반응형


관련글 더보기

댓글 영역