글목록

2021년 4월 5일

정규 분포(Gaussian 분포)를 갖는 난수 생성하기

VBA 뿐만 아니라 엑셀에서도 난수 발생이 가능합니다. 다만, 엑셀에서 난수발생을 위해서는 수식 입력란에 Rand() 함수를 사용하고, VBA에서는 Rnd() 함수를 사용합니다.

VBA의 Rnd()이든 엑셀의 Rand() 함수이든 모두 0~1 사이의 임의의 숫자를 발생시킵니다. 즉, 0~1의 어떤 숫자든 발생될 확률이 동일하다는 것이지요.

예를 들어, 1부터 10까지의 임의의 정수가 무작위로 발생되는 데이터가 필요한 경우에는

tVal=1+Int(Rnd()*10)

와 같이 난수를 발생시킬 수 있습니다. 위와 같이 난수를 여러개 발생시키고나서, 생성된 난수를 히스토그램으로 그려보면 발생된 난수의 갯수가 증가할수록 분포가 균일해지는 것을 알 수 있습니다.

그런데, 간혹, 어떤 평균값을 기준으로 정규 분포(Gaussian 분포)를 갖도록 난수를 발생시키고 싶을 때가 있습니다. 즉, 난수를 여러개 발생시킨 후 히스토그램을 그렸을 때 Gaussian 분포가 되도록 하고 싶다면, 어떻게 해야할까요?


Function GetRandomNum(iMean As Double, iStDev As Double, Optional iGaussian As Boolean = True) As Double
  Dim tN1 As Double, tN2 As Double, tVal As Double
  Select Case iGaussian
    Case True
      Do
        tN1 = 2 * Rnd() - 1
        tN2 = 2 * Rnd() - 1
        tVal = tN1 ^ 2 + tN2 ^ 2
      Loop While (tVal >= 1 Or tVal = 0)
      tVal = Sqr(-2 * Log(tVal) / tVal) * tN1
      GetRandomNum = iMean + tVal * iStDev
    Case False
      tN1 = iMean - Sqr(3) * iStDev
      tN2 = 2 * Sqr(3) * iStDev
      GetRandomNum = tN1 + tN2 * Rnd()
  End Select
End Function


위의 함수는 평균값과 표준편차를 입력한 후, 정규 분포를 가질 것인지, 아니면 일반 분포를 가질 것인지 선택하여 난수를 발생시킨 함수입니다. 일반 분포인 경우, 아래의 Test에서와 같이 쓰면 됩니다만, 평균과 표준편차에 맞게 난수를 발생시키기 위해 위와 같이 작성한 것입니다.

아래의 Test를 실행시키면, 1열에는 0~100까지 일반 분포를 갖는 난수가 생성되고, 2열에는 평균 50, 표준편차 10을 갖는 정류분포형 난수가 생성됩니다. 이렇게 생성된 난수를 히스토그램으로 그려보면 아래와 같은 분포를 가지는 것을 알 수 있습니다.

Sub Test()
  Dim tVal As Double
  For i = 1 To 100
    ActiveSheet.Cells(i, 1).Value = 100 * Rnd()
    ActiveSheet.Cells(i, 2).Value = GetRandomNum(50, 10, True)
  Next
End Sub



어떤 함수에 인위적으로 노이즈를 추가하거나, 통계적 시뮬레이션을 위해 정규분포를 갖는 난수 발생이 필요하실 때, 위의 난수 발생함수를 이용하시면 되겠습니다.

댓글 없음:

댓글 쓰기

의견이나 질문이 있으신 분은 언제든지 댓글을 달아주세요~

많이 본 글 :