http://tibyte.kr/218 에서 이어집니다.
주의) Matlab에서는 특정 분포를 하는 다양한 난수생성을 지원합니다.
이 포스트는 코드를 간단히 구현해 보기 위한 목적으로 matlab을 사용합니다.
정규난수를(normal random variable)얻기 위해 박스-뮬러 변환(Box-Muller Transform) 을 쓸 수 있지만
연산과정에 삼각함수가 들어 있기 때문에
이 복잡성을 해결하기 위해 George Marsaglia가 고안한 극좌표법(polar method)을 쓸 수 있다.
박스뮬러 방법에서 균일랜덤변수 u를 사용하여 sin(2pi*u)와 cos(2pi*u)로 나타냈던 것을
극좌표법에서는 원 위에 무작위로 점(u1, u2)을 찍어서 cos이 밑변/빗변,
sin이 높이/빗변인 것을 이용하여 삼각함수를 대체한다.
박스뮬러 방법에서의 U1이 거리제곱(sq)으로 대체되고,
삼각함수 대신 제곱과 제곱근연산이 들어가게 된다.
[그림 1]
매틀랩 코드로 구현한 결과이다. 표준편차가 1이고 평균이 0인 정규분포를 생성.
N = 1000000;
u1 = zeros(1,N);
u2 = zeros(1,N);
wsq = zeros(1,N);
for i=1:N
sq = 2;
while sq>1
r1 = rand;
r2 = rand;
sq = r1.*r1 + r2.*r2;
end
u1(i) = r1;
u2(i) = r2;
wsq(i) = sq;
end
s = 1;
m = 0;
x = m+s*sqrt(-2*log(wsq)).*u1./(wsq.^0.5);
y = -1.*(m+s*sqrt(-2*log(wsq)).*u2./(wsq.^0.5));
n = horzcat(x,y);
hist(n, 50);
히스토그램 결과.
[그림 2]
이 방법의 단점은 [그림 1]과 코드에서 볼 수 있듯이
점이 원 밖에 찍혔을 경우 평균적으로 1.27배 만큼 난수를 다시 뽑아야 한다는 것이다.
(1.27배는 기하분포의 급수로 계산)