Math và Random Modules
1. Giới thiệu
Python cung cấp hai module quan trọng để làm việc với toán học và số ngẫu nhiên:
- math: Các hàm toán học (lượng giác, logarit, căn bậc,…)
- random: Tạo số ngẫu nhiên và các thao tác ngẫu nhiên
2. Module math
2.1 - Import module
import math
# Hoặc import specific functions
from math import sqrt, pi, sin, cos2.2 - Hằng số toán học
import math
print(math.pi) # 3.141592653589793 (Pi)
print(math.e) # 2.718281828459045 (số e)
print(math.tau) # 6.283185307179586 (2*pi)
print(math.inf) # inf (vô cực)
print(math.nan) # nan (Not a Number)2.3 - Hàm làm tròn
import math
# ceil() - Làm tròn lên
print(math.ceil(4.2)) # 5
print(math.ceil(4.8)) # 5
print(math.ceil(-4.2)) # -4
# floor() - Làm tròn xuống
print(math.floor(4.2)) # 4
print(math.floor(4.8)) # 4
print(math.floor(-4.2)) # -5
# trunc() - Cắt phần thập phân
print(math.trunc(4.8)) # 4
print(math.trunc(-4.8)) # -42.4 - Căn bậc và lũy thừa
import math
# sqrt() - Căn bậc 2
print(math.sqrt(16)) # 4.0
print(math.sqrt(2)) # 1.4142135623730951
# pow() - Lũy thừa
print(math.pow(2, 3)) # 8.0
print(math.pow(5, 2)) # 25.0
# exp() - e^x
print(math.exp(1)) # 2.718281828459045 (e^1)
print(math.exp(2)) # 7.38905609893065 (e^2)
# cbrt() - Căn bậc 3 (Python 3.11+)
# print(math.cbrt(27)) # 3.02.5 - Logarithm
import math
# log() - Logarithm tự nhiên (cơ số e)
print(math.log(math.e)) # 1.0
print(math.log(10)) # 2.302585092994046
# log10() - Logarithm cơ số 10
print(math.log10(100)) # 2.0
print(math.log10(1000)) # 3.0
# log2() - Logarithm cơ số 2
print(math.log2(8)) # 3.0
print(math.log2(1024)) # 10.0
# log(x, base) - Logarithm với cơ số tùy chỉnh
print(math.log(81, 3)) # 4.02.6 - Hàm lượng giác
import math
# Đổi độ sang radian
angle_degrees = 45
angle_radians = math.radians(angle_degrees)
# sin, cos, tan
print(math.sin(angle_radians)) # 0.7071067811865475
print(math.cos(angle_radians)) # 0.7071067811865476
print(math.tan(angle_radians)) # 0.9999999999999999
# Hàm nghịch đảo (trả về radian)
print(math.asin(0.5)) # 0.5235987755982989
print(math.acos(0.5)) # 1.0471975511965979
print(math.atan(1)) # 0.7853981633974483
# Đổi radian sang độ
print(math.degrees(math.pi)) # 180.0
print(math.degrees(math.pi/2)) # 90.02.7 - Giá trị tuyệt đối và dấu
import math
# fabs() - Giá trị tuyệt đối (float)
print(math.fabs(-5.5)) # 5.5
print(math.fabs(3.2)) # 3.2
# copysign() - Copy dấu
print(math.copysign(5, -1)) # -5.0
print(math.copysign(-5, 1)) # 5.02.8 - Tổng hợp và tích
import math
# fsum() - Tổng chính xác của float
numbers = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
print(sum(numbers)) # 0.9999999999999999 (không chính xác)
print(math.fsum(numbers)) # 1.0 (chính xác)
# prod() - Tích các số (Python 3.8+)
print(math.prod([2, 3, 4])) # 24
print(math.prod([1, 2, 3, 4, 5])) # 1202.9 - Factorial và Combinatorics
import math
# factorial() - Giai thừa
print(math.factorial(5)) # 120 (5! = 5*4*3*2*1)
print(math.factorial(0)) # 1
# comb() - Tổ hợp C(n,k) (Python 3.8+)
print(math.comb(5, 2)) # 10 (C(5,2) = 5!/(2!*3!))
# perm() - Hoán vị P(n,k) (Python 3.8+)
print(math.perm(5, 2)) # 20 (P(5,2) = 5!/(5-2)!)2.10 - GCD và LCM
import math
# gcd() - Ước chung lớn nhất
print(math.gcd(48, 18)) # 6
print(math.gcd(100, 50)) # 50
# lcm() - Bội chung nhỏ nhất (Python 3.9+)
print(math.lcm(12, 18)) # 36
print(math.lcm(4, 6, 8)) # 242.11 - Kiểm tra số
import math
# isnan() - Kiểm tra NaN
print(math.isnan(float('nan'))) # True
print(math.isnan(123)) # False
# isinf() - Kiểm tra vô cực
print(math.isinf(float('inf'))) # True
print(math.isinf(123)) # False
# isfinite() - Kiểm tra số hữu hạn
print(math.isfinite(123)) # True
print(math.isfinite(float('inf'))) # False3. Ví dụ thực tế với math
Ví dụ 1: Tính khoảng cách Euclidean
import math
def distance(x1, y1, x2, y2):
"""Tính khoảng cách giữa 2 điểm"""
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
# Test
d = distance(0, 0, 3, 4)
print(f"Khoảng cách: {d}") # 5.0Ví dụ 2: Tính diện tích hình tròn
import math
def circle_area(radius):
"""Tính diện tích hình tròn"""
return math.pi * radius ** 2
def circle_circumference(radius):
"""Tính chu vi hình tròn"""
return 2 * math.pi * radius
r = 5
print(f"Diện tích: {circle_area(r):.2f}")
print(f"Chu vi: {circle_circumference(r):.2f}")Ví dụ 3: Góc giữa 2 vector
import math
def angle_between_vectors(v1, v2):
"""Tính góc giữa 2 vector (độ)"""
# Tích vô hướng
dot_product = v1[0]*v2[0] + v1[1]*v2[1]
# Độ dài vector
mag1 = math.sqrt(v1[0]**2 + v1[1]**2)
mag2 = math.sqrt(v2[0]**2 + v2[1]**2)
# cos(angle) = dot / (mag1 * mag2)
cos_angle = dot_product / (mag1 * mag2)
angle_radians = math.acos(cos_angle)
angle_degrees = math.degrees(angle_radians)
return angle_degrees
v1 = (1, 0)
v2 = (0, 1)
angle = angle_between_vectors(v1, v2)
print(f"Góc: {angle}°") # 90.0°Ví dụ 4: Compound interest
import math
def compound_interest(principal, rate, time, n=1):
"""
Tính lãi kép
principal: Vốn gốc
rate: Lãi suất năm (%)
time: Số năm
n: Số lần tính lãi/năm
"""
amount = principal * math.pow((1 + rate/100/n), n*time)
interest = amount - principal
return amount, interest
# Ví dụ: 10 triệu, lãi 8%/năm, 5 năm, tính lãi hàng tháng
amount, interest = compound_interest(10_000_000, 8, 5, 12)
print(f"Tổng tiền: {amount:,.0f} VND")
print(f"Lãi: {interest:,.0f} VND")4. Module random
4.1 - Import module
import random
# Hoặc import specific functions
from random import randint, choice, shuffle4.2 - Số ngẫu nhiên cơ bản
import random
# random() - Số thực ngẫu nhiên [0.0, 1.0)
print(random.random()) # 0.573124...
# uniform(a, b) - Số thực ngẫu nhiên [a, b]
print(random.uniform(1, 10)) # 5.732...
# randint(a, b) - Số nguyên ngẫu nhiên [a, b]
print(random.randint(1, 10)) # 7
# randrange(start, stop, step)
print(random.randrange(0, 100, 5)) # 0, 5, 10, ... 954.3 - Chọn từ sequence
import random
items = ['apple', 'banana', 'orange', 'grape']
# choice() - Chọn 1 phần tử
print(random.choice(items)) # 'banana'
# choices() - Chọn k phần tử (có thể trùng)
print(random.choices(items, k=3)) # ['apple', 'apple', 'orange']
# sample() - Chọn k phần tử (không trùng)
print(random.sample(items, k=2)) # ['orange', 'apple']4.4 - Choices với trọng số
import random
items = ['A', 'B', 'C', 'D']
weights = [10, 20, 30, 40] # B có khả năng cao hơn A
# Chọn với trọng số
result = random.choices(items, weights=weights, k=1000)
print(f"A: {result.count('A')}") # ~100
print(f"B: {result.count('B')}") # ~200
print(f"C: {result.count('C')}") # ~300
print(f"D: {result.count('D')}") # ~4004.5 - Shuffle (xáo trộn)
import random
items = [1, 2, 3, 4, 5]
random.shuffle(items)
print(items) # [3, 1, 5, 2, 4] (ngẫu nhiên)4.6 - Seed (khởi tạo)
import random
# Set seed để có kết quả lặp lại được
random.seed(42)
print(random.random()) # 0.6394267984578837
random.seed(42)
print(random.random()) # 0.6394267984578837 (giống trên)4.7 - Phân phối Gauss/Normal
import random
# gauss(mu, sigma) - Phân phối chuẩn
# mu: trung bình, sigma: độ lệch chuẩn
values = [random.gauss(100, 15) for _ in range(1000)]
print(f"Mean: {sum(values)/len(values):.2f}") # ~1005. Ví dụ thực tế với random
Ví dụ 1: Tung xúc xắc
import random
def roll_dice(num_dice=1):
"""Tung xúc xắc"""
return [random.randint(1, 6) for _ in range(num_dice)]
# Tung 2 xúc xắc
result = roll_dice(2)
print(f"Kết quả: {result}")
print(f"Tổng: {sum(result)}")Ví dụ 2: Tạo mật khẩu ngẫu nhiên
import random
import string
def generate_password(length=12):
"""Tạo mật khẩu ngẫu nhiên"""
# Tất cả ký tự có thể dùng
characters = string.ascii_letters + string.digits + string.punctuation
# Đảm bảo có ít nhất 1 chữ hoa, chữ thường, số, ký tự đặc biệt
password = [
random.choice(string.ascii_lowercase),
random.choice(string.ascii_uppercase),
random.choice(string.digits),
random.choice(string.punctuation)
]
# Thêm các ký tự ngẫu nhiên còn lại
for _ in range(length - 4):
password.append(random.choice(characters))
# Xáo trộn
random.shuffle(password)
return ''.join(password)
# Test
password = generate_password(16)
print(f"Password: {password}")Ví dụ 3: Rút thăm may mắn
import random
def lucky_draw(participants, num_winners=1):
"""Rút thăm may mắn"""
if num_winners > len(participants):
return "Số người thắng không thể lớn hơn số người tham gia"
winners = random.sample(participants, num_winners)
return winners
# Test
people = ["Alice", "Bob", "Charlie", "David", "Eve", "Frank"]
winners = lucky_draw(people, 3)
print(f"Người thắng: {winners}")Ví dụ 4: Mô phỏng tung đồng xu
import random
def coin_flip(n=1):
"""Tung đồng xu n lần"""
results = [random.choice(['Heads', 'Tails']) for _ in range(n)]
return results
def coin_flip_simulation(n=10000):
"""Mô phỏng tung đồng xu"""
results = coin_flip(n)
heads = results.count('Heads')
tails = results.count('Tails')
print(f"Tổng số lần tung: {n}")
print(f"Heads: {heads} ({heads/n*100:.2f}%)")
print(f"Tails: {tails} ({tails/n*100:.2f}%)")
coin_flip_simulation(10000)Ví dụ 5: Trò chơi đoán số
import random
def guessing_game():
"""Trò chơi đoán số"""
number = random.randint(1, 100)
attempts = 0
max_attempts = 10
print("Tôi đã nghĩ ra một số từ 1 đến 100")
print(f"Bạn có {max_attempts} lần đoán")
while attempts < max_attempts:
try:
guess = int(input(f"\nLần đoán {attempts + 1}: "))
attempts += 1
if guess < number:
print("Quá thấp!")
elif guess > number:
print("Quá cao!")
else:
print(f"Chính xác! Bạn đã đoán đúng sau {attempts} lần")
return
except ValueError:
print("Vui lòng nhập một số!")
print(f"\nHết lượt! Số đúng là {number}")
# guessing_game() # Uncomment để chơiVí dụ 6: Chia nhóm ngẫu nhiên
import random
def split_into_groups(people, group_size):
"""Chia nhóm ngẫu nhiên"""
# Xáo trộn danh sách
shuffled = people.copy()
random.shuffle(shuffled)
# Chia thành các nhóm
groups = []
for i in range(0, len(shuffled), group_size):
groups.append(shuffled[i:i+group_size])
return groups
# Test
students = ["An", "Bình", "Chi", "Dũng", "Em", "Giang", "Hùng", "Lan"]
groups = split_into_groups(students, 3)
for i, group in enumerate(groups, 1):
print(f"Nhóm {i}: {group}")Ví dụ 7: Mô phỏng xác suất
import random
def monty_hall_simulation(n=10000):
"""
Mô phỏng Monty Hall Problem
Thay đổi cửa có lợi hơn không?
"""
stay_wins = 0
switch_wins = 0
for _ in range(n):
# 3 cửa, 1 cửa có xe
doors = [0, 0, 1] # 1 = xe
random.shuffle(doors)
# Người chơi chọn cửa đầu tiên
first_choice = 0
first_choice_value = doors[first_choice]
# Host mở 1 cửa không có xe (không phải cửa người chơi chọn)
# Người chơi chuyển sang cửa còn lại
# Nếu GIỮ NGUYÊN cửa đầu
if first_choice_value == 1:
stay_wins += 1
# Nếu CHUYỂN cửa
if first_choice_value == 0:
switch_wins += 1
print(f"Mô phỏng {n} lần:")
print(f"Giữ nguyên cửa: {stay_wins/n*100:.2f}% thắng")
print(f"Đổi cửa: {switch_wins/n*100:.2f}% thắng")
monty_hall_simulation(10000)Ví dụ 8: Random walk
import random
def random_walk(steps):
"""Mô phỏng random walk 1D"""
position = 0
positions = [position]
for _ in range(steps):
# Di chuyển ngẫu nhiên: -1 hoặc +1
step = random.choice([-1, 1])
position += step
positions.append(position)
return positions
# Test
positions = random_walk(100)
print(f"Vị trí cuối: {positions[-1]}")
print(f"Xa nhất: {max(positions)}")
print(f"Gần nhất: {min(positions)}")Ví dụ 9: Tạo dữ liệu test
import random
import string
def generate_test_data(n=10):
"""Tạo dữ liệu test cho user"""
users = []
for i in range(n):
user = {
'id': i + 1,
'name': ''.join(random.choices(string.ascii_uppercase, k=1)) +
''.join(random.choices(string.ascii_lowercase, k=random.randint(4, 8))),
'age': random.randint(18, 65),
'email': f"user{i+1}@example.com",
'score': random.randint(0, 100)
}
users.append(user)
return users
# Test
users = generate_test_data(5)
for user in users:
print(user)Ví dụ 10: Weighted random selection
import random
class WeightedRandomSelector:
def __init__(self, items_weights):
"""
items_weights: dict {item: weight}
"""
self.items = list(items_weights.keys())
self.weights = list(items_weights.values())
def select(self):
"""Chọn 1 item theo trọng số"""
return random.choices(self.items, weights=self.weights, k=1)[0]
def select_multiple(self, k):
"""Chọn k items theo trọng số"""
return random.choices(self.items, weights=self.weights, k=k)
# Test - Drop rate game items
loot_table = {
'Common': 60,
'Uncommon': 25,
'Rare': 10,
'Epic': 4,
'Legendary': 1
}
selector = WeightedRandomSelector(loot_table)
# Mô phỏng 1000 lần
results = selector.select_multiple(1000)
for rarity in loot_table.keys():
count = results.count(rarity)
print(f"{rarity}: {count} ({count/10:.1f}%)")6. Kết hợp math và random
Ví dụ: Tạo số ngẫu nhiên theo phân phối chuẩn
import random
import math
def normal_distribution_values(mean, std_dev, count):
"""Tạo count số theo phân phối chuẩn"""
values = [random.gauss(mean, std_dev) for _ in range(count)]
return values
def statistics(values):
"""Tính thống kê"""
n = len(values)
mean = sum(values) / n
variance = sum((x - mean)**2 for x in values) / n
std_dev = math.sqrt(variance)
return {
'count': n,
'mean': mean,
'std_dev': std_dev,
'min': min(values),
'max': max(values)
}
# Test
values = normal_distribution_values(mean=100, std_dev=15, count=1000)
stats = statistics(values)
print(f"Count: {stats['count']}")
print(f"Mean: {stats['mean']:.2f}")
print(f"Std Dev: {stats['std_dev']:.2f}")
print(f"Min: {stats['min']:.2f}")
print(f"Max: {stats['max']:.2f}")7. Best Practices
1. Dùng math.fsum() cho tổng chính xác
import math
numbers = [0.1] * 10
# TRÁNH
print(sum(numbers)) # 0.9999999999999999
# TỐT
print(math.fsum(numbers)) # 1.02. Set seed cho reproducibility
import random
# TỐT - Có thể lặp lại kết quả
random.seed(42)
result = random.randint(1, 100)
# Lần sau cũng vậy
random.seed(42)
result2 = random.randint(1, 100)
assert result == result23. Dùng secrets cho security-sensitive
import secrets
# TỐT - Cho mật khẩu, token
token = secrets.token_hex(16)
# TRÁNH - random không đủ an toàn cho security
import random
# weak_token = ''.join(random.choices('0123456789abcdef', k=32))4. Kiểm tra edge cases với math
import math
value = some_calculation()
# TỐT - Kiểm tra trước khi dùng
if math.isnan(value) or math.isinf(value):
print("Invalid value")
else:
print(f"Result: {value}")8. So sánh random vs secrets vs numpy.random
# random - Mục đích chung, KHÔNG an toàn cho crypto
import random
print(random.randint(1, 100))
# secrets - An toàn cho crypto, token, password
import secrets
print(secrets.randbelow(100))
# numpy.random - Khoa học dữ liệu, hiệu suất cao
# import numpy as np
# print(np.random.randint(1, 100))Bài giảng trên YouTube
Cập nhật sau
Last updated on
Python