C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[220] 난수발생기...
나그네 [] 10471 읽음    2001-11-29 09:06
하드 디스크 어디선가 잠자고 있는 자료를 올립니다.
컴퓨터 프로그래밍으로 난수를 발생시키는 방법입니다.

   난수 발생기
   <원제: Quick and Portable Random
     Number Generators>

   ● 글 \ Jerry Dwyer
   필자 Jerry Dwyer는 시카고 대학에서 박사학위를 받았고
   현재 클램슨 대학에서 경제학을 가르치고 있다.
   통계분석과 실험치분석을 위하여 직접 프로그램을 작성하고 있다.
   프로그래머로서의 경력은20여년이며C를사용한지도 10년이 지났다.
   인터네트의 주소는 dwyerg@clemson.edu이다.

   들어가며......
     컴퓨터에서 난수를  발생한다는 것은 상당히 모순적인  이야기처
   럼 들린다.   난수란 글자 그대로  예상할 수 없는 불규칙한  값이
   다. 그러나 컴퓨터는  항상 같은 처리를 하기 때문에 결과가  예측
   가능하다.    일반적으로 컴퓨터에서  말하는 난수 발생기는  특정
   함수를 반복하여 일련의  불규칙한 수열을 얻는다.  이 수열이  임
   의적으로 보일지라도  사실 컴퓨터에 의해 만들어지는  예측가능한
   수열이다. 진정한 의미에서 난수라고 말하기 어렵다.
   그러므로 이러한 난수는  '유사 난수'란 관점으로 보는 것이  정확
   한 의미이다. 그러나 이 기사에서 '유사 난수'는  간단하게  '난수
   '라고 부르기로 한다.  그러나 유사난수를 만드는 것은 쉬운  일이
   아니다.
     이 작업을 위하여 나는 다수의 자료를 참조해야  했으며 이를 참
   조로 한 시뮬레이션을  해 왔다. 이 경험을 참조하여 독자에게  아
   주 일반적으로 적용할 수 있는 난수 발생기를 설명하겠다.
     기사에서 소스로  사용되는 C 언어는  ANSI C를 위주로  하였다.
   그러므로 독자  여러분은 특정  컴파일러로 변환없이도   컴파일을
   시켜볼 수 있다.
     그리고 독자  여러분은 난수  발생기가 유지하는 값들이  어떻게
   오버플로를 피하고 있는지 유의하여 살펴보기 바란다.

   레머 발생기 (Lehmer Generators)
     가장 많이 사용되는 난수 발생기는 1951년 레머  박사에 의해 고
   안된 '배수 일치  난수 발생기'(간단히 레머 발생기라  칭함)이다.
   레머 발생기는 다음의 재귀함수를 참조하고 있다.

     x(t+1)=(a*x(t)) mod m

     여기에서 x(t)는 t회 반복되었을 때의 값을  나타내는데 이 값은
   결국 x(t+1)의 값을 만들어 내는 인자로 사용된다.
    그리고 a는  승수를 mod는 모듈러 함수를   말한다. a*x의 값과 m
   의 값이  모두 양수이면 모듈러 함수는  C에서 말하는 %  연산자와
   같은 기능을 한다.  즉 모듈러 함수의 결과 값은  a*x-[a*x/m]*m의
   결과와 같다.여기에서  []는 []안의 값보다  같거나 적은 가장  큰
   정수를 나타낸다. C에  능통한 사람이라면 정수와 정수사이의  '/'
   연산을 생각하면 된다.
   난수 발생기의  계산에서 연속적인  값들 사이의 관계를  고려하면
   좀더 이해하기 쉽다.<그림 1>은 x(t)가 1에서6까지  임의의 정수라
   고 가정해서 x(t)와 x(t+1)사이의 관계를 보여 주는 그래프이다.
   <그림  1> (A)는  실제 난수에  대한  그래프이다. 실제의  난수는
   x(t)에서 발생하는 값이 x(t+1)에서 발생하는 값과  어떠한 관련도
   맺지 않는다. 즉 완전한 형태의 난수 발생기는  2차원 그래프를 가
   득 채워야한다.또 생성되는 수들은모두 같은 확률을 가지고 있다.
     레머 발생기는  2차원 평면에서 이미  그 난수성을 상실하게  된
   다. 예를 들어 다음 레머 발생기를 생각해 보자.

   x(t+1)=(5*x(t)) mod 7

     초기 값을  1로 했을 때  발생하는 난수는 1,5, 4,  6, 2, 3,  1
   .........이다.  이 수열은 1에서 6까지 발생  가능한 수들이 실제
   로 모두 발생하고  있다. 그러나 이 수열이 2차원 평면을  전부 채
   우지 못한다. <그림  1>의 (b)는 x(t)와 x(t+1)이 어떤 관련을  갖
   고 있음을 보여  준다. 즉 x(t)와 x(t+1)과의 한정된 쌍들만이  존
   재하고 있다.  평면상의 모든 점들은  y=-2x+7, y=-2x+14 두  개의
   직선 위에 존재하고 있다.
     x(t), x(t+1)로 구성된 2차원 평면에서 한 차원  더 높게 생각해
   보자. 즉 x(t), x(t+1), x(t+2)로 구성되는 3차원  평면에서 위 함
   수를 재구성해  보자. 실제  난수들은 2차원에서처럼  3차원에서도
   공간을 가득 채울 것이다. 그러나 레머  발생기는 공간을 메우는데
   실패하고 점이나 선의 형태로서 3차원 공간에서 존재할 뿐이다.
     이 특별한 구조적 모순은 레머 발생기에게는 피할  수 없는 운명
   이다. 그러나 이 취약점이 레머 발생기가  가치가 없다고 단정짓는
   근거가 될 수는 없다.  다른 난수 발생기들이  레머와는 다른 구조
   를 가지고 있지만  위에서 제시된 문제를 해결하고 있는  발생기는
   어디에도 없다.
     레머 발생기는 승수  x(t)와 모듈러 m에 의하여 평면에 찍힐  수
   의 위치가  결정된다. 그러면 문제의  방향은 레머 발생기가  가질
   수밖에 없는 결정론적인  구조에서 벗어나 어떻게 승수 x(t)와  모
   듈러 m의  값을 조정하여 주어진  한정적인 조건에서 가장  타당한
   결과를 만들 수 있을까로 바뀐다.
     레머 발생기가 가지는 결정론적 취약점 외에도 또  한 가지의 약
   점을 가지고 있다. 바로 반복성이다. 승수 5와  모듈러 7의 상황에
   서 레머 발생기는 주기를 6으로 하는 반복값을  가지게 된다. x(t)
   의 값은 주기  6이 지난 후의 값인 x(t+6)의 값과  일치하게 된다.
   그러나 반복 역시 레머 발생기에 한정된 문제는 아니다.
   아무리 난해한 함수를  사용하여도 컴퓨터는 유한 개의 상황  속에
   서 존재하기 때문에 결국 어느 시점에 가서는  이전의 상황으로 복
   귀하게 되고 이때부터 다시 일련의 숫자들이 반복된다.
     일반적으로 레머 발생기에 의하여 만들어지는 값  x(t)에 특정한
   값을 더하는  절차를 만들어서  원시적인 레머 발생기를  세련되게
   할 수  있다. 그러나 결과 값  x(t)에 증가 값을 둠으로서  생기는
   문제가 있다.
     레머 발생기가 0값을 가질 수도 있다는 것이다.  만약 레머 함수
   가 한번 0의  값을 갖게 되면 이어지는 일련의 난수들이  모두 0의
   값을 갖게되는 주기 1의 난수가 생기게 된다.  이런 수열은 난수로
   서의 의미를 상실했다.  증가 값을 두는 것은 0의 값을  가질 수도
   있음을 의미하기 때문에  설계자는 이 점을 반드시 고려하여  알고
   리듬을 구성하여야 한다.
   레머 발생기의 성능을 높이려면?
     비록 레머 발생기가 반복적이고 결정론적인 값을  가진다고 하지
   만 레머 발생기에도좋고 나쁨은 분명히 존재한다.  일례로 주기 값
   을놓고 평가할 수도 있다.앞에서 살펴본 함수는 주시 값이 6이다.

   x(t+1)=(5*x(t)) mod 7

     6 주기의 값은 무척 짧은 값이다.   2^15(32,768)의 값도 복잡한
   계산에서는 신빙성있는 난수  주기가 되지 못한다. 특히  컴파일러
   제조업자는  이 말에  모두  동의할  것이다. 예를  들어  Borland
   C++3.1과 마이크로소프트 사의  Vi-sual C 1.0의 경우에  32비트의
   난수 발생기를  제공하고 있다.  물론 그 주기는  앞의   2^15이나
   32,768의 값보다는 훨씬 길다(그러나 컴파일러가  제공하는 난수발
   생기는 별로 매력적이지 못하다. 우선 이 기사에 나오는 함수보다
   주기가 짧을 뿐  아니라 난수발생기가 이식성이 높지 못하여  오버
   플로의 위험성도 있기 때문이다).
     반복이 나타나지 않는다면  주기는 더 이상 우리의 관심의  대상
   이 될 수  없다. 그러나 앞에서 설명했듯이 난수 발생기에서  반복
   은 필연적이다.  그렇지만 우리가 주기가  매우 긴 난수  발생기를
   만들 수 있고 애플리케이션은 일련의 난수 중  특정 부분만 사용한
   다면 '유사  난수'가 특정  애플리케이션에, 한정적으로는  완벽한
   난수로 역할을 할 수 있다. 이제 독자들도 이  글의 요지를 어림잡
   을 수 있을 것이다.  앞에서 컴퓨터가 만들어 내는 난수의 한계
   성을 고집스럽게 지속하면서  글을 계속한 이유는 바로 이런  눈속
   임 때문이다. 난수는  필연적으로 반복할 수밖에 없지만  사용자의
   관점에서는 얼마든지 이  반복을 피하여 일련의 수열중 특정  부분
   만 사용하여 진정한 난수로 자리 매김을 할 수  있다는 것이다. 승
   수와 모듈러는 주기값을  설정하는 데 결정적인 요소로 작용할  것
   이며 이 값을  어떻게 조정하느냐가 난수 발생기의 좋은  알고리듬
   을 결정하는  열쇠가 된다. 앞에서  제시된 승수와 모듈러의  값은
   예시로 사용하기 위한 보기값에 불과하다.
   주기6의 난수는 사실상  사용할 수 없다. 좀더 긴 주기를  갖는 난
   수 발생기를 만들기 위하여 32비트 정수를 사용하여 보자.
     긴 주기를 가지는  난수 발생기를 만들기 위하여 32비트  정수로
   승수를 만든다.  승수와 모듈러수로 사용할  수 있는 수들은  많이
   있다. 특히 승수와  모듈러의 수를 크게 하면 난수 주기는  일반적
   으로 늘어나기 마련이다. 그러나 승수와 모듈러수는  모두가 CPU의
   부하를 많이 차지한다는 사실을 고려할 때 무작정  크게 잡을 수는
   없다. 그렇다면  어떤 값이  적당할까? 모듈러수로 많이  사용되는
   수가  2^32이다.
   왜일까? 앞에서 정의한 32비트의 부호 정수를  해머 발생기의 승수
   로 사용한다는 사실을 고려해 보자.

     x ← a * x

     x가 가질 수 있는 최고 값은  2^31-1이다  32비트의 최상위 비트
   는 부호비트로 사용된다.  특정 연산의 결과 값이 상위 비트로  캐
   리지가 발생할 수도 있으며 결국 이 캐리지는  사인 버트에 영향을
   미칠  수도 있다.  만약 이런  오버플로를  무시한다면 이  코드는
   2^32의 모듈러수를 가지는 레머 발생기를 구현할  수 있다. 그러나
   위의 기술은 오버플로를 무시한다는 가정에서 출발한  결론일 뿐이
   다. 부호정수는 이런 류의 오버플로를 결코용납하지 않을 것이다.
     ANSI C에서는 오버플로는 특별한 경우로 분류하고  그 동작의 처
   리에 대해서는 정의하지 않겠다. 게다가 이 코드의 효과는 기계의
   정수 표현 방식에 의존하고 있다. 기계나  언어 컴파일러나 심지어
   컴파일러의 버전에 따라서  영향을 많이 받고 있기 때문에  프로그
   램의 이식성을 보장하기는 어렵다. 함수를 더  빠르게 구현하여 속
   도를 증가시키기보다는  이러한 비이식성을 제거하는데 시간을  투
   자하는 것이 더 현명한 일이다.
     모듈러값으로   많이    사용되는   또   다른   하나의    값은
   2^31-1(2147483647) 이다.  왜일까? 이 값이야말로 최장의  주기를
   가질 수 있는 최상의 선택이다.
     더불어 베이식이나  포트란, 파스칼과  같은 언어의  컴파일러가
   표현할 수 있는 최고의 부호 정수값이며 여러  기계에서도 이에 대
   한 표현이 가능하다.
     놀랍게도 더  큰 모듈러값(짝수)을  가지고 있는 난수  발생기의
   주기가 작은 모듈러(홀수)의  주기에 반 정도밖에 안된다.  모듈러
   수 2^32 에서는 초기 값이 홀수라면 주기는 거의 2^30 이른다.
   2^31-1의 모듈러  수에서의 주기는  231-2에 이른다. 이  기사에서
   사용하는 승수들을  테스트한 결과 모두2^31-1의 모듈러에서  최장
   의 주기를 가졌다.  그리고 이 발생기를 기사 후반부에 나오는  결
   합 알고리듬과 합칠 경우 그 주기는 거의   2^61이다. 여러 형태의
   긴 주기 레머 발생기를 가지고 있다면 짧은  주기의 난수 발생기는
   필요하지 않을 것이다.
     승수의 값으로는 어떤 것이 좋을까? 여러분  스스로 승수를 구하
   여 확인을 해  보는 걋?좋을 듯하다. 미안하지만 난수  발생기의
   승수를 결정하는데 있어 어떠한 가이드 라인도 없다.
     어떤 사람들은 이 승수들에 대한 연구를 위하여  많은 시간을 보
   냈고 32비트의 부호  정수를 갖는 기계에서 이식성이 높은  32비트
   난수 발생기를 만들기 위하여 연구하는 사람도 많이 있다.

   이식성 높은 난수 발생기
     이식성 높은 난수  발생기를 만들기 위하여 2^31-1의 모듈러  수
   와 32비트 부호 정수를 사용한다는 것은  앞에서도 밝혔다. 이것은
   결코 어려운 작업이 아니다.
     가장 근본적인 문제는 오버플로의 해결이 될  것이다. 가장 최근
   에 발생한  난수 x(t)와 승수(m)의  곱은 32비트 정수를  초과하는
   경우가 발생하기 때문이다.
     Linus Schrage는 위 곱셈의 결과를 모듈
   Modulus         Multiplier        q         r        10,000th
   Draw
                           Alone
   2^31-1          41,358     51,924    10,855     1,285,562,981
   2^31-1          48,271     44,488    3,399      399,268,537
   2^31-1          69,621     30,845    23,902     190,055,451
   2^31-1          16,807     127,773   2,836      1,043,618,065
                   In combination generator
   2,147,483,563   40,014     53,668    12,211     1,919,456,777
    2,147,483,399  40,692     52,774    3,791      2,006,618,587
      Combination generator with shuffling         804,307,721
        Sources: Park and Miller [5];   L'Ecuyer [2,3]
         <표  1> 레머 발생기에서 유용한 승수와 모듈러수

   러수의 근사치 인수분해를  통하여 해결할 수 있는 방법을  연구하
   였다.    George Fishman과 Louis Moore는 2^31 -1의  모듈러 수를
   가지는 레머 난수기에 대한 연구를 철저히 하여서  아래와 같은 결
   론에 도달했다.
     가장 좋은 승수들은  인수분해가 잘 될만큼 충분히 큰  수이어야
   한다는 것이다. 그럼에도 불구하고 몇몇 승수는  아주 적음에도 불
   구하고 똑같은 정도의 성능을 가지고 있다.
     <표 1>은 자주 예시된  2^31-1의 모듈러값에  대한 4가지의 승수
   를 비교한  값이다. 지난  25년 동안 많은  사람들이 애용한  값은
   16,807이다.
     알고리듬이 옳은지, 틀린지는 어떻게 확인을 할  것인가? 프로그
   램의 실행결과로서 나오는 일련의 수들이 명백한  무작위성을 갖고
   있다는 것을  확인하는 것은 중요한  작업이다. 그러나 이  작업은
   사용하고 있는  프로그램을 통하여  확인하는 것으로 해결할  수가
   없다. 프로그램의 오류를  찾는 것은 새로운 프로그램을  작성하는
   것만큼이나 어려운 작업이기  때문이다. 방법은 직접 발생하는  값
   들을 확인하는 수뿐이다. <표 1>에서 초기값을  1로 하여 10,000번
   째 시행되었을 때  난수 발생기가 만들어 내는 값을 보여  주고 있
   다. 이 작업은 DOS와 OS/2에서 Mathematica와  Borland C를 사용하
   여 나온 결과이다.
     여러분의 프로그램에 이상이  있다면 같은 초기 값을 가지고  출
   발한 발생기가 10,000번째  같은 값을 가질 확률은 거의 0에  가깝
   다고 보아도 무방할 것이다. 이것은 <리스트  1>은 rand.ma라는 파
   일을  보여 주고  있는데 이  파일은  Mathematica   프로그램에서
   10,000번째의 값을 구해 주는 프로그램이다. <리스트  2>의 하단부
   에 있는 C 코드로 부터 나온 결과를 확인하는데  편리한 방식을 제
   시하고 있다.
    <리스트 2>(rand_por.c)는 특별한 승수에 대한 이식성  높은 함수
   를 구현한 것이다.  초기화 코드는 특정 컴파일러에서  오버플로를
   만들 수도있다. 그러나 코드의 나머지 부분은  이식성을 보장할 수
   가 있다. 이  코드에서 가독성과 속도사이에 선택을 할 필요가  있
   을 때마다 나타나는  가독성을 우선시하였다. 가독성에서 가장  중
   요시해야 할  부분은 genr_rand_port함수에서 보여지는 난수  발생
   기의 구현이다.
     이 함수는 4개의  기본적인 외부함수를 갖고 있다.  init_rand와
   rand_port의 두 함수는  표준 C함수의 srand, rand와 상당히  유사
   한 면을 갖고  있다. 여러분이 srand, rand 함수를 통하여  예상하
   듯이 init_rand와   rand_port는 동작을 할 것이다. 또 다른  함수
   로 get_init_rand와 rand_rect_port가  있다. get_init_rand함수는
   init_rand함수로 결과  값을 넘기기  위하여 사용한다고  생각하면
   된다.    잘못된  값으로 init_rand를  호출했다면(0이나 -1과  같
   은),  init_rand_port함수는  에러처리  루틴  값을  받기  위하여
   get_init_rand_port를 호출하게 된다.  init_rand_port로부터 복귀
   된 값은 난수  발생기를 재가동시킬 인자로 사용되어 발생기가  똑
   같은 난수를 만들어 내도록 할 것이다. 일반적으로 사용되는 에러
   처리 루틴 값은  1이기 때문에 함수들은 초기 값을 무시하는  경향
   이 있다.  왜냐하면 에러 처리 루틴  값 1에서 만들어지는  난수가
   임의성이 크지 못하기 때문이다. 승수와 제곱수에  많은 차이가 있
   다고 생각하면 될 것이다. Start up-RANDS로 정의한  16의 값도 이
   런 임의성을 반영한 결과이다.
     <리스트 2>의  rand_rect_port함수는 0에서  1사이의 어떤  값을
   만들어 낸다. 이  값은 0과 1사이에서 정형적인 분산의 성격을  띈
   값이다.
     이 함수는  레머 발생기에서 나온  값을 모듈러로 나눈다.  레머
   발생기가 어떤  시점에서도 0이나 모듈러와  같은 값은 만들  수는
   없다. 그러므로 이함수의 결과는언제나 0에서 1사이가 될 것이다.
     Monte Carlo의 연구에  의하면 난수가 겹치지 않게 만드는  것이
   바람직하다고 한다. <리스트 2>는 init_rand에 의하여 이전에 만
   들어 진 값들을 제외시키기 위하여 skip_ahead라는  함수를 사용하
   고 있다.  rand-pont 함수는 초기  값에서부터 t번째의 값  x(t)를
   구한다. 4,000번째나 1,000번째 같은.......
     이 함수는 중간값을 계산하는 과정이  다소빠릿? 오버플로우가
   없는 이  계산은 희망하는 출력 값을  얻기 위해서는 다음과  같은
   주의사항이 있다.

   (a^skip * init_rand) mod m

     모듈러 수 m보다  skip의 값이 반드시 작아야 한다.  skip_ahead
   와 mult_mod함수는 오버플로우를 피하기 위하여 근사치 인수분해
   와 함께 Russian Peasant 알고리듬을 사용하고 있다.
     '세상에 공짜는  없다'는 말처럼  이식성과 긴 주기를  보장하기
   위해서는 필연적으로  속도에 문제를  일으키기 마련이다.  필자의
   개인적인 의견으로는  속도에서 오는  손실(단순한 속도의  저하가
   아니라 타당한 속도를  유지하기 위하여 발생되는 난수 발생기  프
   로그램을 운영하는 기계의 확장)은 큰 문제가  아니라고 생각한다.
   rand_port함수는 결코  느리다고 말할  수 없다. 필자가  보유하고
   있는 66MHz 486컴퓨터와  OS/2의 환경에서 100,000개의 난수를  발
   생하는데 약  0.23초가 소요되었다. 이것은 Borland의  오버플로를
   사용하였을 때 걸린 시간인 0.09초와 비교가  된다. 성능이 심각한
   문제를 야기시키는 것은  16비트 도스 환경에서이다. 이식성  함수
   는 Borand 함수가 0.22초가 걸린 것에 비하여 약 1.5초 정도가 더
   소요되었다. 그러나 필자는  같은 가격에서는 이식성이 높고 약  2
   배의 주기를  가지고 있는(더구나 이  함수는 이전에 발생한  값을
   피할 수도 있다) 레머 발생기를 취하겠다.

   결합과 혼합
     약 21억?해당하는2^31-2의 값이 여러 목적에  이용하기에 결코
   작은 값이 아니기  때문에 더 큰 주기의 난수 발생기를  별도로 필
   요로 하는  경우는 발생하지 않는다.  그러나 레머 발생기는  일단
   완전히 주기에 돌입해야 비로소 신뢰성있는 결과를 만들어 낸다.
     도입부에서 살펴본 <그림  1>의 그래프는 난수 발생기의  사용에
   있어서 문제가 되는 요소를 보여 주고 있다.
     이 문제와 주기의  문제를 완화시킬 수 있는 두 가지  기술이 있
   는데 하나가 결합이고 다른 하나는 혼합이다.
     레머 발생기에서 나온 값들을 결합하는 것은 그  합이나 차를 이
   용하여 결과를 만든다는  것이다. L'Ecuyer는 <그림 1>과 같은  평
   면의 문제를 효과적으로 없애기 위하여 두 수의  차를 이용할 것을
   제안한다.   <리스트  3>의   레머  발생기의   값들의  차는   약
   2.31x10^18 의 주기를 갖게 된다.
     난수 발생기의 결과  값을 혼합하는 것은 주기의 길이와  임의성
   의 보장이라는 측면에서 또 다른 해결  방안을 제시한다. 기본적인
   생각은 무척 단순하게 보인다. 레머 발생기의  수열만을 취하기 보
   다는 몇 개의  값을 기억시켜 놓고 그 중 하나를  임의적으로 뽑아
   서 사용한다는 것이다.
     특정 승수나 모듈러  수에서 발생기의 값을 섞어서 주기를  실제
   적으로 연장시키는 것은  분석적으로 결론을 내리기가 어렵다.  그
   러나 이 기술은  최소한 난수 발생기의 성능을 저하시키지는  않을
   것이다  일련의  수는 연속된 값의 집합은 아니기 때문에  더욱 임
   의적으로 보인다. 혼합은 특별히 난수 발생기가  최악의 상황에 도
   달했을 때  빛을 발한다. 왜냐하면  이전에 정장된 값들이  현재의
   난수 발생기가 처한 문제를 해결할 수있는 열쇠가 되기 때문이다.
     <그림 3>의 Rand_com.c파일은 두 개의 난수  발생기의 결과를 결
   합하고 혼합하는 함수이다.  위에서의 <표1>은 두 개의 난수  발생
   기를 결합하였을 때의 10,000번째의 결과 값을 보여 주고 있다.
     <리스트 3>은 이전  값을 제외시킨 skip_ahead 과정이  제외되었
   다. 난수  발생기의 결과 값을  혼합시킨다면 이전에 나온  난수가
   주기 내에는 다시  나오지 않는다는 보장을 할 수 없기  때문이다.
   그러나 2.31x  10^18의 주기를 조금 줄일  수 있는 여유가  있다면
   <리스트 2>의 skip ahead함수를 이용하기 위하여  <리스트 3>도 수
   정할 수 있을 것이다. <리스트 3>의  혼합과정을 제외하고 <리스트
   2>의 skip ahead 함수를 적용하면 된다.
     결과적으로 여러분이 잘 작동하고 빠르며 똑같은  정도의 확률을
   가지는 난수 발생기를 원한다면 필자는 rand_port를 추천할 수 있
   다. 만약 여러분이  더 긴 주기를 가지며 비록 속도면에서  저하가
   발생하는 한이 있어도  난수로서의 성격이 더 분명한 함수를  희망
   한다면 필자는 rand_comb를 추천한다.

   참 고 서 적
   [1] George S. Fishman and Louis R. Moore III.
      "An Exhaustive Analysis of Multiplicative Co
   ngruential Random-Number Generators with M
   odulus 2^31-1"
     SIAM Journal on Scientific and Statistical Co
   mputing January: 1986

   [2] Pierre L'Ecuyer.
      "Efficient and Portable Combined Random
   Number Generators"
      Communications of the ACM June: 1988

   [3] Pierre L'Ecuyer
      "Random Numbers for Simulation"
      Communications of the ACM October: 1990

   [4] Donald Knuth
      The Art of Computer Programming, Vol 2,
   "Seminumerical Algorithms"
      Reading MA:Addison Wesley, 1981  pp441-
   443

   더 깊게 공부하고 싶다면......
     독자 여러분이 난수 발생기에 관한 더 많은  지식을 쌓고 싶다면
   위에서 언급한  Donald Knuth의  저서 제 3장에서부터  시작하기를
   권한다.
     이 책은 난수  발생기에 관하여 고전이 된 책이다. 고전이  가지
   고 있는 의미에는 두 가지가 있다. 그 첫  번째가 시기적으로 뒤쳐
   졌다는 말이다.  Bratley, Fox,  Schrage는 Donald보다 훨씬  나은
   관점을 제시하고 있다. James는 선택적 난수  발생기라는 분야에서
   독보적인 자리를 차지하고  있다. 여러분이 쉽게 접할 수 있는  책
   을 아래에 기록하였으니 앞으로도 지속적으로 참조하기 바란다.

   Bratley, Paul, Bennett L. Fox and Linux E. Schrage.
     A Guide to Simulation, Second Edition.
        New York NY: Springer Verlag, 1987

   James, F.
    "A Review of Pseudorandom Number Generators"
       Computer Physics Communications.
       October 1990

   Press, William H., et al.
     Numerical Recipes in C, Second Edition.
        Cambridge: Cambridge University Press, 1992

   Park, Stephen K. and Keith W. Miller.
     "Random-Number Generators: Good Ones Ard
      Hard to Find"
        Communications of the ACM. October 1988

   L'Ecuyer, Pierre, and Serge Coti.
     "Implementing a Random-Number Package
      with Splitting Facilities"
        ACM Transactions on Mathematical Software.
        March 1991

+ -

관련 글 리스트
220 난수발생기... 나그네 10471 2001/11/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.