12. 확률 및 난수 생성: random 모듈

확률 및 난수 생성: random 모듈 | 지식에 대한 탐구

소개

 

확률과 난수 생성은 컴퓨터 과학, 통계학, 시뮬레이션, 게임 개발 등 다양한 분야에서 중요한 역할을 합니다. Python의 random 모듈은 이러한 작업을 수행하기 위한 다양한 함수와 메서드를 제공합니다. 이 글에서는 random 모듈의 주요 기능과 사용법, 그리고 실제 응용 사례를 상세히 살펴보겠습니다.

1. random 모듈 기본

 

1.1 모듈 임포트

random 모듈은 Python 표준 라이브러리의 일부이므로 별도의 설치 없이 바로 사용할 수 있습니다.

import random  # random 모듈 임포트

1.2 난수 생성기 초기화

random 모듈은 기본적으로 시스템 시간을 시드(seed)로 사용합니다. 하지만 재현 가능한 결과를 위해 시드를 명시적으로 설정할 수 있습니다.

random.seed(42)  # 42는 임의의 정수입니다. 시드 설정

2. 기본적인 난수 생성

 

2.1 실수 난수 생성

2.1.1 random()

0.0 이상 1.0 미만의 실수를 무작위로 반환합니다.

print(random.random())  # 예: 0.6394267984578837

2.1.2 uniform(a, b)

주어진 범위 [a, b] 내의 실수를 무작위로 반환합니다.

print(random.uniform(1.0, 10.0))  # 예: 5.437587656137344

2.2 정수 난수 생성

2.2.1 randint(a, b)

주어진 범위 [a, b]의 정수를 무작위로 반환합니다. a와 b를 포함합니다.

print(random.randint(1, 10))  # 예: 7

2.2.2 randrange(start, stop[, step])

range() 함수와 유사하게 동작하며, 주어진 범위 내의 정수를 무작위로 선택합니다.

print(random.randrange(0, 101, 2))  # 0부터 100까지의 짝수 중 하나를 선택

3. 시퀀스 관련 함수

 

3.1 choice(seq)

주어진 시퀀스에서 무작위로 하나의 요소를 선택합니다.

fruits = ['apple', 'banana', 'cherry']
print(random.choice(fruits))  # 예: 'banana'

3.2 choices(population, weights=None, k=1)

주어진 모집단에서 중복을 허용하여 k개의 샘플을 선택합니다. 가중치를 지정할 수 있습니다.

print(random.choices(fruits, weights=[5,1,1], k=3))  # 예: ['apple', 'apple', 'cherry']

3.3 sample(population, k)

주어진 모집단에서 중복 없이 k개의 샘플을 선택합니다.

print(random.sample(range(1, 51), k=6))  # 로또 번호 생성 예: [3, 19, 28, 35, 44, 45]

3.4 shuffle(x)

주어진 시퀀스를 무작위로 섞습니다.

deck = list(range(1, 53))  # 1부터 52까지의 카드
random.shuffle(deck)
print(deck[:5])  # 섞인 덱에서 상위 5장 출력

4. 확률 분포

 

random 모듈은 여러 가지 확률 분포에 따른 난수 생성 함수를 제공합니다.

4.1 정규 분포 (가우시안 분포)

4.1.1 gauss(mu, sigma)

평균이 mu이고 표준편차가 sigma인 정규 분포에서 난수를 생성합니다.

print(random.gauss(0, 1))  # 표준 정규 분포 (평균 0, 표준편차 1)

4.1.2 normalvariate(mu, sigma)

gauss()와 동일한 기능을 하지만, 다른 알고리즘을 사용합니다.

print(random.normalvariate(0, 1))

4.2 기타 분포

  • random.betavariate(alpha, beta): 베타 분포
  • random.expovariate(lambd): 지수 분포
  • random.gammavariate(alpha, beta): 감마 분포
  • random.lognormvariate(mu, sigma): 로그 정규 분포
  • random.weibullvariate(alpha, beta): 웨이불 분포

 







 

5. 실제 응용 사례

 

5.1 간단한 주사위 게임 시뮬레이션

두 명의 플레이어가 주사위를 던져 높은 숫자가 나온 사람이 이기는 게임을 시뮬레이션해보겠습니다.

def roll_dice():
    return random.randint(1, 6)

def play_game():
    player1 = roll_dice()
    player2 = roll_dice()
    
    print(f"Player 1 rolled: {player1}")
    print(f"Player 2 rolled: {player2}")
    
    if player1 > player2:
        return "Player 1 wins!"
    elif player2 > player1:
        return "Player 2 wins!"
    else:
        return "It's a tie!"

# 게임 실행
for _ in range(3):  # 3번 게임 진행
    print("\nNew game:")
    result = play_game()
    print(result)

5.2 몬테카를로 방법을 이용한 원주율(π) 추정

난수를 사용하여 원주율을 추정하는 몬테카를로 시뮬레이션을 구현해보겠습니다.

import math

def estimate_pi(n):
    inside_circle = 0
    total_points = n
    
    for _ in range(total_points):
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        
        if x*x + y*y <= 1:
            inside_circle += 1
    
    pi_estimate = 4 * inside_circle / total_points
    return pi_estimate

# 시뮬레이션 실행
simulations = [10000, 100000, 1000000]
for n in simulations:
    estimated_pi = estimate_pi(n)
    print(f"Estimated π with {n} points: {estimated_pi}")
    print(f"Error: {abs(estimated_pi - math.pi)}")
    print()

5.3 간단한 암호 생성기

random 모듈을 사용하여 간단한 암호 생성기를 만들어보겠습니다.

import string

def generate_password(length=12, use_punctuation=True):
    characters = string.ascii_letters + string.digits
    if use_punctuation:
        characters += string.punctuation
    
    password = ''.join(random.choice(characters) for _ in range(length))
    return password

# 암호 생성 예시
print("12-character password:", generate_password())
print("16-character password without punctuation:", generate_password(16, False))

6. 보안 관련 주의사항

 

random 모듈은 의사 난수 생성기(Pseudorandom Number Generator, PRNG)를 사용합니다. 이는 암호학적으로 안전하지 않을 수 있습니다. 보안이 중요한 애플리케이션(예: 암호화 키 생성)에서는 secrets 모듈을 사용하는 것이 좋습니다.

import secrets

# 암호학적으로 안전한 난수 생성
secure_random_number = secrets.randbelow(100)  # 0 이상 100 미만의 정수
secure_random_bits = secrets.randbits(32)  # 32비트 정수

# 암호학적으로 안전한 토큰 생성
secure_token = secrets.token_hex(16)  # 32자의 16진수문자열

 

Python의 random 모듈은 다양한 확률 분포와 난수 생성 기능을 제공하여 시뮬레이션, 게임 개발, 통계적 샘플링 등 다양한 분야에서 활용될 수 있습니다. 기본적인 난수 생성부터 복잡한 확률 분포까지 다양한 기능을 제공하므로, 상황에 맞는 적절한 함수를 선택하여 사용하는 것이 중요합니다.

random 모듈을 효과적으로 사용하기 위해서는 기본적인 확률 이론과 각 함수의 특성을 이해하는 것이 필요합니다. 또한, 시드 설정을 통해 재현 가능한 결과를 얻을 수 있다는 점을 기억하세요. 이는 디버깅과 테스트에 매우 유용할 수 있습니다.

마지막으로, 보안이 중요한 애플리케이션에서는 random 모듈 대신 secrets 모듈을 사용해야 한다는 점을 꼭 기억하세요. random 모듈은 예측 가능한 시퀀스를 생성할 수 있으므로, 암호화 키 생성이나 보안 토큰 생성 등에는 적합하지 않습니다.

random 모듈은 계속해서 발전하고 있으며, 새로운 버전의 Python에서는 추가적인 기능이나 최적화된 알고리즘이 도입될 수 있습니다. 따라서 공식 문서를 주기적으로 확인하고, 최신 버전의 특징을 파악하는 것이 좋습니다.

실제 문제에 random 모듈을 적용해보면서 경험을 쌓는 것이 가장 효과적인 학습 방법입니다. 다양한 시나리오에 대해 시뮬레이션을 수행해보고, 결과를 분석하면서 확률과 통계에 대한 직관을 발전시킬 수 있을 것입니다.

추가 학습 자료

 

© 2024 지식에 대한 탐구. All rights reserved.