프로그래밍을 하다보면 특히 게임쪽에서 랜덤(random) 또는 난수 를 생성할 일이 있다.
난수는 무작위 숫자를 뜻하지만 컴퓨터 쪽에선 100% 무작위(랜덤)은 아니다.
정해진 난수표에서 숫자를 가저오는 방식이기 때문이다.


자바(JAVA) 에서 난수를 생성하는 방식은 크게 두가지 이다.


첫번째로 Math.random() 이용하는 방식이다.
Math Class의 random 함수는 double 형 타입으로 0.0 이상 1.0 미만 사이의 값을 반환한다.

 

public class TestRandom {
    public static void main(String[] args) {        
        for(int i =0; i < 10; i++) {
            System.out.print(Math.random()+" ");
        }
        System.out.println("");
    }
}

 

* 결과 값 :

0.1652487713090327 0.286398184817342 0.4336343206580924 0.4295581874855847 0.44636521032290466 0.8715008193305886 0.93917325018134 0.5647002564584279 0.7323427296788428 0.8295767550811228

 

보통은 자연수의 난수가 필요한 경우가 많기 때문에 아래 예제 처럼 0부터 9까지의 난수가 필요하다면 x10을 한 이후에 int형으로 강제 형변환을 시켜주면 된다.

 

public class TestRandom {
    public static void main(String[] args) {        
        for(int i =0; i < 10; i++) {
            System.out.print((int)(Math.random()*10) + " ");
        }
        System.out.println("");
    }
}

 

* 결과 값 :

2 6 3 7 6 9 8 7 9 7 


하지만 이 방식은 직관적이지 않고 형변환등을 하면서 익셉션(Exception) 처리등을 해주어야 하기 때문에 두번째 방식을 추천한다.

 


 

 

 

 

두번째로 Random Class를 이용하는 방식이다.
난수를 생성하는데 필요한 기능 등을 묶어놓은 클레스 이다.
Random Class를 사용하려면 import java.util.Random; 를 해주어야 한다.
Random Class의 맴버변수중에 setSeed를 이용하거나 생성자에 매개변수로 시스템시간을 매개로 전달하면 난수표의 시드값을 초기화 할 수 있다.
아래는 0부터 9까지의 정수를 출력하는 예제이다.

 

import java.util.Random;
 
public class TestRandom {
    public static void main(String[] args) {        
        Random random = new Random(System.nanoTime());
        for(int i =0; i < 10; i++) {
            System.out.print((int)(random.nextInt(10)) + " ");
        }
        System.out.println("");
    }
}


* 결과 값 :


1 3 3 7 6 9 5 7 2 4


아래는 1부터 45까지의 숫자를 출력하는 로또 번호 추첨 예제이다. 랜덤으로 숫자를 추첨하는데 기존에 나왔던 숫자가 있을 경우 다시 재추첨하도록 하였다.

 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
public class TestRandom {
    public static void main(String[] args) {        
        Random random = new Random(System.nanoTime());
        List<Integer> result = new ArrayList<Integer>();
        int num;
        for (int i = 0; i < 6; i++) {
            while (true) {
                num = random.nextInt(45) + 1;
                if (result.contains(num)) {
                    continue;
                } else {
                    result.add(num);
                    System.out.print(num+" ");
                    break;
                }
            }
        }    
        System.out.println("");
    }
}

 

* 결과 값 :

 

12 38 33 29 4 17 

 

 

아래 테이블은 다양한 Random class의 멤버함수 들이다. 이외에도 다양한 함수들이 많이 존재하니 라이브러리를 참고하도록 하자.

함수 설명
nextInt(int i) 0부터 i 까지의 랜덤한 숫자를 리턴
nextInt() Int 타입의 최소 ~ 최대범위 안에서 랜덤한 숫자를 리턴
nextLong() Long 타입의 최소 ~ 최대범위 안에서 랜덤한 숫자를 리턴
nextDouble() Double 타입의 0.0 – 1.0까지의 랜덤한 숫자를 리턴
nextBoolean() boolean타입의 true, false 중 랜덤한 값을 리턴

 

참고 자료 : https://docs.oracle.com/javase/8/docs/api/java/util/Random.html

Posted by 꿈만은공돌
,

 프로그램을 만들다보면 숫자를 랜덤으로 만들어내야 할 때가 있습니다. 이번 포스팅은 C언어와 C++에서 랜덤으로 숫자를 추출하는 방법과 여러 예제를 살펴보겠습니다.


1. rand 함수의 기본 사용 방법


rand 함수를 사용하면 랜덤으로 숫자를 출력할 수 있습니다.


함수 원형은 아래와 같습니다. 

int rand(void)


#include<stdlib.h>로 stdlib.h 헤더파일에 해당 선언이 적혀있습니다. 


해당 함수는 0 부터 32767까지의 숫자 중 하나를 랜덤으로 뽑아냅니다.


여기에 % 연산자를 사용하여 원하는 숫자의 범위를 정합니다.


예를들어 rand() % 10 을 하면 0부터 9까지의 숫자중 하나가 나오게 됩니다.


만약 5부터 10까지의 숫자 중 를 랜덤으로 추출하고 싶다면 


rand() % 6 + 5 를 하면 됩니다. rand() % 6 을 하면 0부터 5까지의 숫자 중 하나이고 거기에 +5를 하면 5부터 10까지의 숫자중 하나가 됩니다.


이렇게 하면 자신이 원하는 숫자를 랜덤으로 추출할 수 있습니다.


아래 사용예제 입니다. 0부터 99까지의 숫자중 랜덤으로 변수 num에 저장하여 출력합니다.

총 3번을 반복합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
 
void main() 
{        
    int num;
    num = rand() % 100;
    printf("rand : %d\n", num);
    num = rand() % 100;
    printf("rand : %d\n", num);
    num = rand() % 100;
    printf("rand : %d\n", num);
}
cs


- 출력결과 -

rand : 41

rand : 67

rand : 34




2. srand 함수를 사용하여 프로그램을 실행할 때마다 다른 난수 출력하기


 하지만 이상한 것은 프로그램을 실행 할 때마다 매번 같은 숫자가 나오게 됩니다.

이것은 프로그램을 실행할 때마다 항상 난수표에 같은 지점에서부터 숫자를 추출하기 때문입니다.

난수표라는 것은 글 가장 마지막에 설명을 써놓았습니다.


 그래서 프로그램을 실행할 때마다 숫자가 다르게 나오게 하고 싶다면 srand 함수를 이용해야 합니다.

아래 함수의 원형 입니다.


void srand( unsigned int seed );


 seed값을 받아 난수표에 시작 지점을 바꾸는 것 입니다. 보통은 seed로 현재의 시간을 unsigned int 로 변환하여 사용하게 됩니다. 그러면 프로그램을 시작하는 시간이 계속 달라지기 때문에 프로그램을 실행할 때마다 다른 수가 추출되게 됩니다.


srand 함수를 사용하기 위해서는 #include<time.h>를 추가하여야 합니다.


아래 사용예제 입니다. 위의 예제와 같지만 프로그램이 시작할때 scanf() 를 사용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
 
void main() 
{        
    int num;
    srand(time(0));
    num = rand() % 100;
    printf("rand : %d\n", num);
    num = rand() % 100;
    printf("rand : %d\n", num);
    num = rand() % 100;
    printf("rand : %d\n", num);
}
cs


출력결과가 매번 다릅니다.




3. 알파벳 랜덤으로 출력


아래 예제는 응용한 것으로 알파벳 소문자 a부터 z중 하나를 출력하는 예제입니다.

알파벳 개수가 26개기 때문에 rand() % 26 을하고 +'a' 를 합니다. 아스키2 코드를 이용 하는 것입니다.

그러면 a부터 z중 하나의 숫자가 출력됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
 
void main() 
{        
    int i;
    char ch;
    srand(time(0));
    for (i = 0; i < 10; i++) {
        ch = rand() % 26 + 'a';
        printf("rand : %c\n", ch);
    }
}
cs


- 출력결과 -

rand : e 

rand : s 

rand : b 

rand : f 

rand : i 

rand : p 

rand : n 

rand : b 

rand : j 

rand : d 






4. 로또 번호 추첨


1부터 45까지의 숫자를 중복없이 6개 출력하는 로또 번호추첨 예제이다. 


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
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
 
#define MAX 45 //1부터 45 숫자
#define NUMBER //6개 숫자출력
 
void main() 
{        
    int i, tmp;
    int save[NUMBER];
    int count = 0;
    int isSame = 0;
    srand(time(0));
    
    //숫자 추출
    while (count < NUMBER) {
        isSame = 0;
        tmp = rand() % MAX + 1;//1부터 45 출력
        for (int i = 0; i < count; i++) { //중복검사
            if (tmp == save[i]) { //중복이 있을때
                isSame = 1;
                break;
            }
        }
        if (isSame == 0) { //중복없음
            save[count] = tmp;
            count++;
        }
    }
 
    //결과 출력
    printf("추첨 숫자 : ");
    for(i =0; i < NUMBER; i++)    
        printf("%d ", save[i]);
    printf("\n");    
}
cs


- 출력결과 -

추첨 숫자 : 35 15 29 19 27 38




5. 프로그래밍 언어에서 난수(랜덤)란?


 추가로 사실 대부분에 프로그램에서 사용하는 랜덤 함수들은 정밀하게는 완벽한 랜덤이 아닙니다. 난수표 라고해서 특성 숫자들이 적힌 테이블이 있는데 이 테이블들을 순서대로 출력하는 것 입니다. 

 예를들어 1 5 4 2 0 3 7 6 란 숫자가 있으면 1을 선택하고 그 다음에는 5를 선택하고 이런식으로 차례대로 숫자를 선택합니다. 이와 같은 방식으로 C와 C++에서는 0부터 32767 까지의 숫자들이 난수표에 적혀 있습니다. 그래서 엄밀하게는 완벽한 랜덤이라고 할 수 는 없습니다.

 따라서 보안이 중요한 곳이나 이런데서는 랜덤함수를 사용할때 주의가 필요합니다. 랜덤함수를 사용하여 추출한 결과를 보면 다음 수를 예측하거나 하는 방법으로 해킹등을 할 수도 있기 때문입니다.

Posted by 꿈만은공돌
,