Math và Random modules
1. Giới thiệu
Phần tiêu đề “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
Phần tiêu đề “2. Module math”2.1 - Import module
Phần tiêu đề “2.1 - Import module”import math
# Hoặc import specific functionsfrom math import sqrt, pi, sin, cos2.2 - Hằng số toán học
Phần tiêu đề “2.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
Phần tiêu đề “2.3 - Hàm làm tròn”import math
# ceil() - Làm tròn lênprint(math.ceil(4.2)) # 5print(math.ceil(4.8)) # 5print(math.ceil(-4.2)) # -4
# floor() - Làm tròn xuốngprint(math.floor(4.2)) # 4print(math.floor(4.8)) # 4print(math.floor(-4.2)) # -5
# trunc() - Cắt phần thập phânprint(math.trunc(4.8)) # 4print(math.trunc(-4.8)) # -42.4 - Căn bậc và lũy thừa
Phần tiêu đề “2.4 - Căn bậc và lũy thừa”import math
# sqrt() - Căn bậc 2print(math.sqrt(16)) # 4.0print(math.sqrt(2)) # 1.4142135623730951
# pow() - Lũy thừaprint(math.pow(2, 3)) # 8.0print(math.pow(5, 2)) # 25.0
# exp() - e^xprint(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
Phần tiêu đề “2.5 - Logarithm”import math
# log() - Logarithm tự nhiên (cơ số e)print(math.log(math.e)) # 1.0print(math.log(10)) # 2.302585092994046
# log10() - Logarithm cơ số 10print(math.log10(100)) # 2.0print(math.log10(1000)) # 3.0
# log2() - Logarithm cơ số 2print(math.log2(8)) # 3.0print(math.log2(1024)) # 10.0
# log(x, base) - Logarithm với cơ số tùy chỉnhprint(math.log(81, 3)) # 4.02.6 - Hàm lượng giác
Phần tiêu đề “2.6 - Hàm lượng giác”import math
# Đổi độ sang radianangle_degrees = 45angle_radians = math.radians(angle_degrees)
# sin, cos, tanprint(math.sin(angle_radians)) # 0.7071067811865475print(math.cos(angle_radians)) # 0.7071067811865476print(math.tan(angle_radians)) # 0.9999999999999999
# Hàm nghịch đảo (trả về radian)print(math.asin(0.5)) # 0.5235987755982989print(math.acos(0.5)) # 1.0471975511965979print(math.atan(1)) # 0.7853981633974483
# Đổi radian sang độprint(math.degrees(math.pi)) # 180.0print(math.degrees(math.pi/2)) # 90.02.7 - Giá trị tuyệt đối và dấu
Phần tiêu đề “2.7 - Giá trị tuyệt đối và dấu”import math
# fabs() - Giá trị tuyệt đối (float)print(math.fabs(-5.5)) # 5.5print(math.fabs(3.2)) # 3.2
# copysign() - Copy dấuprint(math.copysign(5, -1)) # -5.0print(math.copysign(-5, 1)) # 5.02.8 - Tổng hợp và tích
Phần tiêu đề “2.8 - Tổng hợp và tích”import math
# fsum() - Tổng chính xác của floatnumbers = [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])) # 24print(math.prod([1, 2, 3, 4, 5])) # 1202.9 - Factorial và Combinatorics
Phần tiêu đề “2.9 - Factorial và Combinatorics”import math
# factorial() - Giai thừaprint(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
Phần tiêu đề “2.10 - GCD và LCM”import math
# gcd() - Ước chung lớn nhấtprint(math.gcd(48, 18)) # 6print(math.gcd(100, 50)) # 50
# lcm() - Bội chung nhỏ nhất (Python 3.9+)print(math.lcm(12, 18)) # 36print(math.lcm(4, 6, 8)) # 242.11 - Kiểm tra số
Phần tiêu đề “2.11 - Kiểm tra số”import math
# isnan() - Kiểm tra NaNprint(math.isnan(float('nan'))) # Trueprint(math.isnan(123)) # False
# isinf() - Kiểm tra vô cựcprint(math.isinf(float('inf'))) # Trueprint(math.isinf(123)) # False
# isfinite() - Kiểm tra số hữu hạnprint(math.isfinite(123)) # Trueprint(math.isfinite(float('inf'))) # False3. Ví dụ thực tế với math
Phần tiêu đề “3. Ví dụ thực tế với math”Ví dụ 1: Tính khoảng cách Euclidean
Phần tiêu đề “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)
# Testd = 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
Phần tiêu đề “Ví 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 = 5print(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
Phần tiêu đề “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
Phần tiêu đề “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ángamount, 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
Phần tiêu đề “4. Module random”4.1 - Import module
Phần tiêu đề “4.1 - Import module”import random
# Hoặc import specific functionsfrom random import randint, choice, shuffle4.2 - Số ngẫu nhiên cơ bản
Phần tiêu đề “4.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
Phần tiêu đề “4.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ố
Phần tiêu đề “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')}") # ~100print(f"B: {result.count('B')}") # ~200print(f"C: {result.count('C')}") # ~300print(f"D: {result.count('D')}") # ~4004.5 - Shuffle (xáo trộn)
Phần tiêu đề “4.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)
Phần tiêu đề “4.6 - Seed (khởi tạo)”import random
# Set seed để có kết quả lặp lại đượcrandom.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
Phần tiêu đề “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ẩnvalues = [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
Phần tiêu đề “5. Ví dụ thực tế với random”Ví dụ 1: Tung xúc xắc
Phần tiêu đề “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ắcresult = 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
Phần tiêu đề “Ví dụ 2: Tạo mật khẩu ngẫu nhiên”import randomimport 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)
# Testpassword = generate_password(16)print(f"Password: {password}")Ví dụ 3: Rút thăm may mắn
Phần tiêu đề “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
# Testpeople = ["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
Phần tiêu đề “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ố
Phần tiêu đề “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
Phần tiêu đề “Ví 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
# Teststudents = ["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
Phần tiêu đề “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
Phần tiêu đề “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
# Testpositions = 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
Phần tiêu đề “Ví dụ 9: Tạo dữ liệu test”import randomimport 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
# Testusers = generate_test_data(5)for user in users: print(user)Ví dụ 10: Weighted random selection
Phần tiêu đề “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 itemsloot_table = { 'Common': 60, 'Uncommon': 25, 'Rare': 10, 'Epic': 4, 'Legendary': 1}
selector = WeightedRandomSelector(loot_table)
# Mô phỏng 1000 lầnresults = 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
Phần tiêu đề “6. Kết hợp math và random”Ví dụ: Tạo số ngẫu nhiên theo phân phối chuẩn
Phần tiêu đề “Ví dụ: Tạo số ngẫu nhiên theo phân phối chuẩn”import randomimport 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) }
# Testvalues = 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
Phần tiêu đề “7. Best Practices”1. Dùng math.fsum() cho tổng chính xác
Phần tiêu đề “1. Dùng math.fsum() cho tổng chính xác”import math
numbers = [0.1] * 10
# TRÁNHprint(sum(numbers)) # 0.9999999999999999
# TỐTprint(math.fsum(numbers)) # 1.02. Set seed cho reproducibility
Phần tiêu đề “2. 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ậyrandom.seed(42)result2 = random.randint(1, 100)assert result == result23. Dùng secrets cho security-sensitive
Phần tiêu đề “3. Dùng secrets cho security-sensitive”import secrets
# TỐT - Cho mật khẩu, tokentoken = secrets.token_hex(16)
# TRÁNH - random không đủ an toàn cho securityimport random# weak_token = ''.join(random.choices('0123456789abcdef', k=32))4. Kiểm tra edge cases với math
Phần tiêu đề “4. Kiểm tra edge cases với math”import math
value = some_calculation()
# TỐT - Kiểm tra trước khi dùngif 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
Phần tiêu đề “8. So sánh random vs secrets vs numpy.random”# random - Mục đích chung, KHÔNG an toàn cho cryptoimport randomprint(random.randint(1, 100))
# secrets - An toàn cho crypto, token, passwordimport secretsprint(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
Phần tiêu đề “Bài giảng trên YouTube”Cập nhật sau