Random Number Algorithm Ch.1
<난수의 정의와 종류>

http://wahnfried.net









 자연계열의 교과과정을 공부하고, 공과대학을 나왔음에도 goo는 수학을 정말로(!) 못 합니다. 남들이 보기에는 꽤 괜찮은 spec.을 갖고 있음에도 스스로는 '왜 난 입으로 먹고 사는 전공을 택하지 않았던 걸까' 라고 후회하고 회의하는 그런 부류의 학생이었거든요.

 난데 없이 알고리즘 - '까짓거 standard library에 있는 거 갖다 쓰면 되잖아' 라고 스스로 도망다녔던 - 이라는 것에 대해서 글을 적게 된 건, 얼마 전 신선한 정신적인 충격을 지인으로부터 받으면서 '내가 이렇게 살면 안 되겠구나;' 라고 반성한 탓이기도 합니다. 머리 속에 있는 것들을 끄집어 내면서 앞으로 한동안은 이 주제로 글을 적어나가는 반성과 학습과 회고의 시간이 될 것 같네요.









0. Intro : Random Number


 말 그대로 난수(亂數)란 일련의 Random 한 Number 를 이야기합니다. 프로그래밍 세계에서 많은 순간 활용되는 녀석이기도 하지요. 아래의 예들은 난수를 갖고 만들어내는 것이 너무나 당연하게 생각되는 사례들입니다.


게임에서 :
A 가 B 를 때릴 때 30%의 확률로 타격 Miss 가 발생한다.

메신저의 대화상대 매칭 프로그램이라면 :
조건에 맞는 대화상대를 임의의 순서로 섞어 (Shuffling) 유저에게 보여준다.

기타 :
카드게임의 카드를 섞는다, 랜덤하게 어떤 카드를 선택한다 등등등



 문제는, 난수를 generate 하는 주체가 사람이라면, 아무나 붙잡고 '숫자를 아무 거나 대 봐!' 라고 종용하는 것만으로도 말 그대로의 두서 없고 연관성 없는 (Random한) 숫자들의 나열이 가능할 수 있겠지만, 우리의 성실한 컴퓨터는 언제나처럼 '저더러 뭘 보고 숫자를 대라는 말입니까?' 라고 반문하겠지요. 때문에 이 똑똑한 친구에게는 난수를 계산하기 위한 일련의 공식이라는 것이 필요하게 됩니다. 그리고 사실 이런 점 때문에 컴퓨터를 갖고는 완전한 의미의 난수를 만들어낸다는 것이 사실 불가능한 일이 될 수도 있답니다. 공식이나 법칙 자체가 규칙이 되어버리니까 말이지요!



1. 컴퓨터로 난수를 생성하기 위해서는 공식(법칙) 이 필요하다.

2. 공식에 기반한 난수 생성은 진정한 의미의 난수이기 어렵다.










1. Random Number Table


 정말 제대로 된 '좋은 난수'의 기준은 무엇일지에 대해 생각해보도록 합시다. 일단은 말 그대로 엉망진창의 숫자들이 마구 튀어나와야 좋을 거라고 생각해볼 수 있겠지요. 난수를 만드는 수학 공식이라는 것을 하나 만들고 난수를 뽑아 보았는데 처음엔 1, 두 번째엔 2, 세 번째엔 3이 나오면 아무리 봐도 좋은 난수가 아니라는 생각이 들게 됩니다.

 그런 경우를 배제하고 다시 난수를 짜 보았더니 이번에는 1 - 0 - 3 - 2 - 5 - 4 - 7 - 6 이라는순서로 난수가 나왔다면 이것 역시 다음 숫자를 예측할 수 있는 경우이니 좋다고 말하기는 힘들게 됩니다.

 다시 생각해서 뽑아보았더니 이번에는 1 - 7 - 19 - 24 - 1 - 91 - 8 - 1 - 63 - 22 - 1 - 34 가 나왔습니다. 꽤 괜찮아 보이지만 1이라는 숫자가 너무 자주 나오는군요.

 왠지 머리가 아파지지요. 어찌 되었거나 이런 고민 끝에 어떤 사람들이 어떤 이유로 나름대로 잘 선택된 수의 나열을 표로 짜 둔 것이 있는데, 이것을 난수표 (Random Number Table) 라고 합니다. 물론 공식으로 뽑아낸 숫자들 중 쓸만한 배열들을 표로 남긴 경우도 있겠지만, 말 그대로 손으로 끄적끄적 적어 만든 것이라면, 난수라는 개념에 가장 근접한 것이 난수표가 아닐까 싶네요.

 옛날 옛날의 아주 기초적인 암호학 (Cryptography) 의 예에서, 알파벳을 암호화 하는 방법으로, 26 개의 난수를 영문 알파벳 26 자와 1:1 로 Matching 시켜서 긴 숫자로 문장을 감추기도 했다고 하니, 이런 경우에는 암호를 만드는 이와 해석하는 이가 같은 난수표를 갖고 있었겠지요. 이런 것들이 난수의 시작이 아니었을까.. 하고 생각해봅니다.










2. Pseudo - Random Number


 적당한 범위의 숫자에서 만들어내는 난수라면, 사람이 손으로 만든 난수표로 가장 아름다운 난수를 만들어낼 수도 있겠지만, 프로그래밍 세계에서 우리가 일반적으로 쓰는 자료형의 범위인 4 byte ( = 2 ^ (8 * 4) 가지의 값을 표현할 수 있는 ) 의 난수를, 수억 번, 수조 번 뽑아내야 하는 경우라면 종이로 만든 난수표를 늘어놓는다면 지구를 몇 바퀴 돌게 될 지도 모르는 일입니다. 그리고 앞서 말한 컴퓨터라는 친구의 근본적인 한계 때문에도 사람들은 난수를 수학적인 방법으로 접근할 수밖에 없었구요. 이것을 의사 난수 (Pseudo - Random Number) 라고 부릅니다.



 Pseudo Random Number (의사 난수)

 공식, 알고리즘을 통해 만들어내는 난수로, 만드는 과정 자체가 공식에 의해 결정적이므로 진정한 난수로 보기는 힘들다.



 앞서 언급한 '좋은 난수' 의 기준과는 상관 없이, 어떤 수들의 나열을 만들어내는, 즉 수열을 뽑아내는 것이라면 의사 난수의 점화식으로 볼 수 있겠지요. 하지만 경우에 따라 사용자가 원하는 난수의 조건이 다르고, 원하는 특성도 다르기 때문에 다양한 방법과 점화식들이 나오게 됩니다.











3. Conditions of Random Number


 난수라는 것이 되도록 예측 불가능한 수들을 만들어내는 것이 목표라지만, 경우에 따라서 난수의 사용자들은 여러 조건들을 요구할 수도 있습니다. 예를 보지요. 왠지 머리속에서는 게임에나 나올 법한 상황들만 자꾸 떠오르네요. 아무래도 카드게임을 기본으로 난수라는 것을 생각하게 되었기 때문이 아닐까 싶은데..;



RPG 게임에서 몬스터를 잡았다 :

몬스터는 빨강, 파랑, 노랑 세 가지의 물약을 정확히 1/3 씩의 확률로 유저에게 준다.


=> 조건 1.  1 = 빨강, 2 = 파랑, 3 = 노랑이라고 하면 ( 1, 3 ) 의 범위 내의 숫자를 만드는
                난수여야 한다.

=> 조건 2.  난수 선택을 시행할 때 1, 2, 3 이 선택될 확률은 정확히 동일해야 한다.



 위와 같은 경우라면 숫자의 범위와 동일한 확률이라는 조건이 필요하게 됩니다. 물론 현업에서 일하는 분들을 보면 확률 문제를 정말 '딱 떨어지게' 처리하지는 않는 편입니다만, 보통의 경우 가장 많이 요구되는 형태의 난수가 위와 같은 것들입니다. 매우 선형적이고 (linear) 확률이 균등하게 분포된 (Uniform Distribution) 난수인 셈이지요. 이런 형태의 난수를 보통 일양난수(一樣亂數) 혹은 Uniform Random Number 라고 부릅니다.



시뮬레이션 게임에서 새로 태어난 NPC의 IQ를 정한다 :

대부분의 자연 현상은 정규분포 (Normal Distribution) 를 따른다고 가정한다.


=> 조건 1.  IQ 수치는 평균이 100, 표준편차가 16인 정규분포이다.



 시뮬레이션이나 게임에서는 자연 현상의 일부를 표현하기 위해 - 날씨의 변화라거나 사회적인 현상을 표현하는 등 - 자연현상의 놀라운 특징인 정규분포를 따르는 난수를 사용해야 하는 경우가 있습니다. 매번 선택되어 나오는 숫자는 제각각인 것 같지만, 결과적으로 각 수치의 발생 빈도를 그려나가면 우리가 익숙한 종 형태의 정규분포 그래프가 나와야 하는 것이지요. 이런 형태의 난수를 정규분포난수 Normal Distribution Random Number 라고 부릅니다.

 이 외에 카드를 섞는 경우 등에서는 현실에서의 우리가 카드를 섞을 때, 섞다 보면 잘 섞인 카드를 다시 되돌려놓기도 하고 앞뒤 카드의 순서는 바꾸지 않은 채로 뭉치 단위로 섞기도 하는 것처럼 말 그대로의 엉망진창의 난수값을 필요로 할 수도 있고.. 경우에 따라 원하는 난수의 특성이 다를 수 있다는 것은 언뜻 생각해보면 알 수 있습니다. 이런 상황에 따라 원하는 난수를 찾아내고 혹은 멋지지는 않더라도 만들어낼 수 있는 건 순전히 프로그래머의 역량이 되겠지요?










4. Outro


 난수에 대한 개요만 이야기해보았는데, 이 이후로는 슬슬 난수 알고리즘의 기본부터 들어가볼까 합니다. goo의 깜냥이 얼마나 받쳐줄는지는 모르겠습니다만, 스스로의 공부를 위한 것이니 착실하게 조사하고 적어나갈까 합니다. 아마도 첫 시작은 가장 간단한 선형 합동법 (Linear Congruential Method) 가 되겠지요?