Language/Python

Python - random(), 임의의 수(난수)를 구하는 함수

TechNote.kr 2019. 3. 20. 00:09
728x90


가장 흔히 사용되는 기능으로 random 값을 생성하는 random() 함수가 있다. 해당 함수를 사용하기 위해서는 별도의 random module을 import 하여 사용해야 한다. 


직접 난수를 구하는 로직을 작성해 본 사람을 알겠지만 규칙이 없는 난수를 생성하기는 쉽지가 않다. 질 좋은 난수 생성기더라도 경우의 수를 늘려 생성하다 보면 어느 순간 규칙을 가지는 것을 확인하는 경우가 다수이기 때문이다. 


이를 극복하기 위해 난수 생성하는 로직이 제안되고 존재하는데 Python 에서는 Mersenne Twister 라는 난수 생성기를 사용한다. 하지만 이 난수 생성 로직도 특정 상황에서 다음 난수를 예측할 수 있기 때문에 암호 관련 목적으로 random 모듈로 부터 생성된 난수 사용은 권장하지 않고 있다.  



 가장 기본이 되는 random.random() 함수의 기본 사용법은 다음과 같다.


>>> import random
>>> random.random()
0.06190390162927073

random.random() 함수는 random module 을 사용하기 때문에 기본적으로 random module 을 import 해야 한다. 생성된 난수는 [0.0, 1.0), 즉 0 이상 1 미만의 실수를 균등한(uniformly) 확률로 반환한다. 


만약 특정 범위 내의 임의의 정수인 난수를 구하고 싶다면 다음과 같이 random.randrange()를 사용하면 된다. 

random.randrange(0, 10) 을 사용하면 0 <= N < 10 범위의 정수인 난수를 구할 수 있다. 

>>> import random
>>> random.randrange(0,10)
0
>>> random.randrange(0,10)
3
>>> random.randrange(0,10)
5
>>> random.randrange(0,10)
6
>>> random.randrange(0,10)
0


특정 간격의 실수인 난수를 구하고 싶다면 다음과 같이 추가 인자를 줄 수도 있다. 

>>> random.randrange(0, 10, 3)
3
>>> random.randrange(0, 10, 3)
9
>>> random.randrange(0, 10, 3)
6


특정 리스트내 인자들 중 하나를 임의로 골라야 한다면 random.choice() 함수를 사용할 수도 있다. 

>>> random.choice([2,6,3,8,5])
5
>>> random.choice([2,6,3,8,5])
5
>>> random.choice([2,6,3,8,5])
2
>>> random.choice([2,6,3,8,5])
3


숫자 뿐만 아니라 다음과 같이 문자/문자열 또한 임의로 선택할 수 있다. 

>>> random.choice(['a', 'b', 'c'])
'b'
>>> random.choice(['a', 'b', 'c'])
'c'
>>> random.choice(['a', 'b', 'c'])
'a'


리스트에서 특정 인자를 추출해 내는 것이 아니라 리스트내 순서를 바꾸고 싶다면 random.shuffle() 함수를 다음과 같이 사용할 수도 있다. 

>>> array = ['a', 'b', 'c', 'd', 'e', 'f']
>>> array
['a', 'b', 'c', 'd', 'e', 'f']
>>> random.shuffle(array)
>>> array
['c', 'a', 'e', 'd', 'b', 'f']
>>> random.shuffle(array)
>>> array
['c', 'f', 'd', 'a', 'e', 'b']
>>> random.shuffle(array)
>>> array
['a', 'b', 'c', 'e', 'd', 'f']


주어진 리스트에서 특정 갯수의 인자를 무작위를 추출하고 싶다면 random.sample() 함수를 이용하면 된다.

>>> array = ['a', 'b', 'c', 'd', 'e', 'f']
>>> array
['a', 'b', 'c', 'e', 'd', 'f']
>>> random.sample(array, 3)
['d', 'b', 'a']
>>> random.sample(array, 3)
['c', 'd', 'f']
>>> random.sample(array, 3)
['a', 'f', 'c']


쉽게 이해할 수 있는 random module 내 함수들의 예를 언급해 보았는데, 이 뿐만 아니라 각종 distribution에 따른 난수 생성 방법 또한 지원하고 있고, 앞서 언급한 Mersenne Twister가 아닌 다른 generator 로도 난수 생성을 할 수도 있다. 



Python 도 여타 다른 언어와 마찬가지로 임의의 난수를 생성하기 위해서는 난수 생성기를 초기화하기 위한 숫자인 seed 값을 설정해주어야 한다. 만약 seed 인자 설정시 None을 넘겨주거나 아무것도 넘겨 주지 않으면, 그냥 이 때는 현재 system time이 seed 값으로 사용된다.


(아예 random.seed() 를 호출하지 않아도 random.random()을 호출하면 난수가 잘 생성되는데, 이 때 random seed 는 내부적으로 어떻게 처리되는지 궁금하다.)


만약 random seed를 시간과 같은 임의의 수가 아닌 아래와 같이 고정된 숫자를 쓰면 어떻게 될까?


>>> import random
>>> random.seed(1)
>>> random.random()
0.13436424411240122
>>> random.random()
0.8474337369372327
>>> random.random()
0.763774618976614
>>>
>>> random.seed(1)
>>> random.random()
0.13436424411240122
>>> random.random()
0.8474337369372327
>>> random.random()
0.763774618976614
>>>
>>> random.seed(1)
>>> random.random()
0.13436424411240122
>>> random.random()
0.8474337369372327
>>> random.random()
0.763774618976614


위의 예를 잘 보면 동일한 random seed 에 대해서 이후 생성되는 난수들은 동일한 값을 가지고 순차적으로 생성되고 있음을 확인할 수 있다. seed 를 고정값으로 사용하면 임의의 규칙이 있는 숫자가 생성되어 버리는 것이다. 따라서 계속 변화하는 난수를 만들고 싶다면 seed 로 계속 변화하는 시간과 같은 값을 사용해야 함을 알 수 있다. 







728x90