8-2-나.난수의 생성

random 함수 자체는 간단하지만 응용하기에 따라서는 아주 다양한 유형의 난수를 만들 수 있다. 유형별로 random 함수의 응용예를 보도록 하자.

 

 0~n사이의 난수는 random(n)으로 생성한다. 이때 생성되는 난수의 범위에 인수 그 자체는 제외되며 난수 중 제일 큰 값은 n-1이다.

 

random(10)       // 0~9 까지의 난수

random(89)       // 0~88 까지의 난수

 

 random 함수가 만들어내는 난수의 최소값은 항상 0으로 고정되어 있다. 난수 범위의 끝 값은 인수 n으로 조정하며 범위의 시작값은 random 호출 결과에 상수를 더해 조정한다.

 

random(10)+1         // 1~10까지의 난수

random(20)+10   // 10~29 까지의 난수

 

random 함수로 생성한 난수에 상수를 더하면 난수의 범위가 평행이동된다.

난수의 범위가 평행 이동되면 범위의 끝도 같이 이동되므로 미리 계산에 포함하여 범위도 적당히 줄여야 한다. 5~10 사이(10은 제외)의 난수를 만들고 싶다고 해서 random(10)+5라고 호출해서는 안되며 random(5)+5라고 호출해야 한다. 일정한 범위의 난수 생성문을 일반적으로 정의하면 다음과 같다.

 

a~b사이(b 제외)의 정수 난수를 구할 때 : random(b-a)+a;

a~b까지(b 포함)의 정수 난수를 구할 때 : random(b-a+1)+a;

 

 난수 사이의 간격은 난수를 구한 후 곱을 사용한다. 이때 범위를 지정하는 인수는 곱해주는 수를 미리 나누어 구해야 한다. 만약 0~100 미만의 짝수 중 하나를 구하고자 한다면 다음과 같이 한다.

 

random(100/2)*2

 

100/2는 50이므로 random 함수에 의해 0~49사이의 난수가 생성되며 이 값에 2를 곱하면 0~98로 범위가 확장된다. 정수에 2를 곱했으니 생성된 난수는 모두 짝수일 수밖에 없다. 만약에 홀수를 구하고 싶다면 1을 더하면 될 것이다.

 실수 난수가 필요하면 먼저 충분한 크기의 정수 난수를 구하고 필요한 유효자리수만큼 10의 거듭승으로 나눈다. 소수점 한자리까지 유효한 0.0~9.9사이의 난수는 다음과 같이 생성하면 된다.

 

random(100)/10.0

 

random(100)에 의해 0~99까지의 정수가 생성되는데 이 값을 10.0으로 나누면 0.0~9.9까지로 범위가 축소될 것이다. 이때 나누어주는 수는 반드시 실수 상수여야 / 연산자가 실수 나눗셈을 하게 된다. 소수점 두 자리까지 유효한 실수 난수는 0~1000까지 정수 난수를 구한 후 100.0으로 나누면 된다.

 분리된 범위의 난수도 원한다면 생성할 수 있다. 다음 예는 0~4, 14~18 사이의 두 범위에 있는 수 중 하나를 골라준다.

 

(random(5)+5)*(random(2)==0 ? 1:-1)+9

 

(random(2)==0 ? 1:-1) 연산문은 앞에서 생성한 난수의 부호를 난수로 선택하는 역할을 한다. random(2)가 0이라는 표현은 1/2의 확률을 의미한다. 사실 이 예는 좀 억지스럽고 실용성이 없지만 이런 식으로도 응용할 수 있다는 것을 보여주기에는 충분하다.

 전혀 연관성이 없는 수들 중 하나를 난수로 선택할 수도 있다. 예를 들어 3, 7, 12, 15 중 하나를 선택하고 싶다고 한다면 다음과 같이 하면 된다.

 

int i;

do {

     i=random(16);

} while (i!=3 && i!=7 && i!=12 && i!=15);

 

원하는 난수가 나올 때까지 루프를 계속 돌리기만 하면 된다. 다음 장에서 배울 배열을 사용하면 배열에 원하는 값들을 넣어 놓고 배열의 첨자를 난수로 고를 수도 있다. 이런 식으로 제어구조까지 활용하면 사실 못만들어낼 난수가 없는 셈이다.

난수의 활용 용도는 무궁 무진한데 불규칙한 수의 생성 뿐만 아니라 확률을 제어하고 싶을 때도 사용된다. if (random(n) == 0) { } 조건문은 일정한 확률로 어떤 문장을 실행한다. 예를 들어 if (random(10) == 0) 은 열번에 한 번꼴로, 10%의 확률로 참이 된다. 난수의 범위가 넓을수록 확률은 작아지고 좁을수록 확률이 커진다. 이때 ==0은 별 의미가 없으며 1이나 2와 비교를 해도 똑같은 결과를 얻을 수 있다.