IDL/Math

중복되지 않는 난수들의 생성법 (업데이트)

이상우_IDL 2020. 1. 2. 17:19
728x90

제가 예전에 "중복되지 않는 난수 산출법"이라는 게시물을 올린 적이 있습니다. 2015년도 7월이니까 벌써 4년도 넘은 게시물인데요. 일단 이 게시물의 링크는 다음과 같습니다.


중복되지 않는 난수 산출법 (2015. 7. 10)


그런데 이 당시 올렸던 내용에 대하여 수정이 필요한 부분이 있어서 이번에 업데이트된 내용으로 다시 올리고자 합니다. 이 게시물에서 소개되었던 예제 코드가 있었는데요. 이 내용을 다음과 같이 수정하겠습니다.


PRO test_random_exclusive_20200102


n = 8; number of values

ul = 8; upper limit

r1 = ROUND(RANDOMU(seed, n)*ul)

r2 = r1[UNIQ(r1, SORT(r1))]

n1 = N_ELEMENTS(r1)

n2 = N_ELEMENTS(r2)

PRINT, 'initial array'

PRINT, '  number of values :', n1

PRINT, '  number of exclusive values :', n2

PRINT, '  array values :', r1

WHILE n2 LT n1 DO BEGIN

  nr = n1 - n2

  rr = ROUND(RANDOMU(seed, nr)*ul)

  r1 = [r2, rr]

  r2 = r1[UNIQ(r1, SORT(r1))]

  n1 = N_ELEMENTS(r1)

  n2 = N_ELEMENTS(r2)

ENDWHILE

PRINT, 'final array'

PRINT, '  number of values :', n1

PRINT, '  number of exclusive values :', n2

PRINT, '  array values (in order) :', r1

r1_new = ARRAY_SCRAMBLE(r1)

PRINT, '  array values (scrambled) :', r1_new


END


예전의 코드와 지금 올린 코드 사이에는 몇가지 차이점들이있습니다. 가장 큰 부분은 UNIQ 함수의 사용 방식입니다. 이 UNIQ 함수가 사용된 부분이 새로운 버전에서는 다음과 같습니다.


r2 = r1[UNIQ(r1, SORT(r1))]


그런데 예전 버전에서는 다음과 같았습니다.


r2 = r1[UNIQ(r1)]


사실은 제대로 하려면 새로운 버전에서와 같이 UNIQ 함수 내에서 SORT 함수의 결과를 두번째 인수로 이용하는 것이 맞습니다. 예전 버전에서는 제가 SORT 함수도 이용해야 한다는 것을 미처 언급하지 못했었는데, 이건 제 실수입니다. 이번 버전에서와 같이 SORT 함수로함께 사용해야 하는 것이 맞습니다. 그 이유에 대해서는 제가 UNIQ 함수에 관하여 소개했던 관련 게시물에서 자세히 언급을 했기 때문에 필요하시면 그 내용을 참조하시기 바랍니다. 그리고 제가 최근에 소개했던 ARRAY_SCAMBLE 함수도 사용되도록 하였습니다. 그 이유는 결과로 얻어지는 배열의 값들이 올림차순으로 정렬되기 때문에 다시 한번 순서를 휘저어주는 것이 좋을 것 같아서입니다. 어쨌든 위와 같은 새로운 내용의 코드로 실행을 해본 예제 결과는 다음과 같습니다.


initial array

  number of values :     8

  number of exclusive values :     5

  array values :     3     7     6     4     6     8     4     6

final array

  number of values :     8

  number of exclusive values :     8

  array values (in order) :     2     3     4     5     6     7     8     1

  array values (scrambled) :     7     8     4     3     2     5     1     6


어차피 대상 배열을 난수로 생성하기 때문에 결과는 실행할 때마다 매번 달라지겠지만, 여러분들도 직접 해보시면 달라진 점들을 느끼실수 있을 것입니다. 그리고 코드의 맨 앞부분에서 등장하는 n은 배열의 값 갯수이고 ul은 배열의 값들의 상한값입니다. 만약 50을 넘지않는 10개의 값들을 무작위로 뽑아내고자 한다면 앞부분의 변수 설정만 다음과 같이 바꿔주면 됩니다.


n = 10; number of values

ul = 50; upper limit


이렇게 하여 얻은 예제 결과는 다음과 같습니다.


initial array

  number of values :    10

  number of exclusive values :     9

  array values :   27   32   43   14   14   15   41   12   37    3

final array

  number of values :    10

  number of exclusive values :    10

  array values (in order) :    3   12   14   15   27   32   37   41   43   23

  array values (scrambled) :   43   14   32   12   15   41   23   37    3   27


그래서 예전에 올렸던 내용이지만 수정 및 업데이트가 필요할 것 같아서 이와 같이 다시 다듬어서 소개해보았습니다.

LIST