Chia sẻ
"RAND và RANDARRAY thay đổi mỗi khi chỉnh sửa worksheet. Bài viết hướng dẫn xây Seeded RNG bằng LAMBDA + SCAN — tạo số ngẫu nhiên ổn định, reproducible, chỉ đổi khi đổi seed."
RAND và RANDARRAY thay đổi mỗi khi bạn chỉnh sửa worksheet — khiến kết quả ngẫu nhiên không bao giờ ổn định. Bài viết hướng dẫn xây dựng Seeded RNG bằng LAMBDA — tạo số ngẫu nhiên có thể tái tạo, chỉ thay đổi khi bạn muốn.
Vấn Đề Với RAND Và RANDARRAY
Excel có 3 hàm ngẫu nhiên: RAND(), RANDBETWEEN(), và RANDARRAY(). Cả 3 đều là hàm volatile — nghĩa là chúng tính lại mỗi khi worksheet thay đổi, kể cả khi bạn chỉnh sửa ô hoàn toàn không liên quan.
Ví dụ thực tế: Bạn dùng RANDARRAY để chia 30 học sinh vào 6 nhóm ngẫu nhiên. Kết quả hiển thị hoàn hảo... cho đến khi bạn nhập tên 1 học sinh mới — toàn bộ nhóm bị xáo trộn lại.
Giải pháp cổ điển: Copy → Paste Values. Nhưng cách này phá hủy công thức gốc và cần làm thủ công mỗi lần. Chúng ta cần thứ tốt hơn — một Seeded Random Number Generator (RNG).
Seeded RNG Là Gì?
Seeded RNG tạo số ngẫu nhiên dựa trên một giá trị khởi đầu gọi là seed. Đặc điểm quan trọng:
Cùng seed → cùng kết quả: Chạy 2 lần với seed = 42 luôn cho ra dãy số giống hệt nhau.
Khác seed → khác kết quả: Seed = 42 và seed = 43 cho dãy số hoàn toàn khác.
Không volatile: Kết quả chỉ thay đổi khi bạn đổi seed — không bị ảnh hưởng bởi thao tác khác.
Mọi ngôn ngữ lập trình đều có seeded RNG (Python: random.seed(), JavaScript: các thư viện seed random). Excel thiếu tính năng này, nhưng chúng ta có thể tự xây bằng LAMBDA.
Thuật Toán Park-Miller
Chúng ta sẽ dùng thuật toán Park-Miller LCG (Linear Congruential Generator) — một trong những RNG đơn giản và được chứng minh toán học nhất. Công thức:
next = MOD(a × current, m)
Trong đó:
a = 16807 (hằng số nhân)
m = 2147483647 (2³¹ - 1, số nguyên tố Mersenne)
current = seed ban đầu hoặc kết quả trước đóVí dụ với seed = 42:
Bước 1: MOD(16807 × 42, 2147483647) = 705894
Bước 2: MOD(16807 × 705894, 2147483647) = 1126542223
Bước 3: MOD(16807 × 1126542223, 2147483647) = 1579310009
...
Để chuẩn hóa về [0, 1]: chia cho m
705894 / 2147483647 = 0.000329
1126542223 / 2147483647 = 0.5245
1579310009 / 2147483647 = 0.7354Bước 1: Triển Khai Bằng LET (Cột Phụ)
Cách đơn giản nhất — dùng cột phụ cho chuỗi seed:
// Ô B1: nhập seed (ví dụ: 42)
// Ô A2: =B1 (seed ban đầu)
// Ô A3 trở đi:
=LET(
a, 16807,
m, 2147483647,
MOD(a * A2, m)
)
// Ô B2 trở đi (chuẩn hóa 0-1):
=A2 / 2147483647Mỗi ô A nhận kết quả ô trước đó làm seed → tạo chuỗi ngẫu nhiên. Đổi B1 → toàn bộ dãy thay đổi. Không chỉnh B1 → dãy ổn định.
Bước 2: Tạo Hàm LAMBDA (Không Cần Cột Phụ)
Dùng REDUCE để lặp qua thuật toán và trả về mảng kết quả — không cần cột phụ:
=LAMBDA(seed, n,
LET(
a, 16807,
m, 2147483647,
seq, SEQUENCE(n),
result, REDUCE(
seed,
seq,
LAMBDA(acc, _,
MOD(a * acc, m)
)
),
result / m
)
)Lưu ý: REDUCE trả về giá trị cuối cùng, không phải mảng tất cả bước. Để có mảng đầy đủ, dùng SCAN thay REDUCE:
// Đặt tên RAND_SEED trong Name Manager:
=LAMBDA(seed, n,
LET(
a, 16807,
m, 2147483647,
seq, SEQUENCE(n),
raw, SCAN(
seed,
seq,
LAMBDA(acc, _,
MOD(a * acc, m)
)
),
raw / m
)
)Sau khi đặt tên, sử dụng:
=RAND_SEED(42, 10)
→ Trả về mảng 10 số ngẫu nhiên [0,1), luôn cùng kết quả với seed=42
=RAND_SEED(A1, 20)
→ 20 số ngẫu nhiên, đổi A1 để shuffle lại5 Ứng Dụng Thực Tế
1. Chia học sinh vào nhóm ngẫu nhiên
// B1 = seed (đổi mỗi tháng), A2:A31 = danh sách 30 học sinh
=SORTBY(A2:A31, RAND_SEED(B1, 30))
→ Sắp xếp ngẫu nhiên danh sách dựa trên seed
→ Cùng seed = cùng thứ tự, đổi seed = shuffle mới2. Chọn ngẫu nhiên N phần tử từ danh sách
// Chọn 5 người thắng giải từ 100 ứng viên:
=INDEX(
SORTBY(A2:A101, RAND_SEED(B1, 100)),
SEQUENCE(5)
)
→ 5 người đầu tiên sau khi shuffle3. Tạo dữ liệu mẫu ổn định
// Doanh thu ngẫu nhiên 10-500 triệu:
=RAND_SEED(42, 20) * 490 + 10
→ 20 giá trị [10, 500], KHÔNG thay đổi khi edit worksheet4. Random A/B testing
// Phân nhóm A/B cho 1000 khách hàng:
=IF(RAND_SEED(99, 1000) < 0.5, "A", "B")
→ Kết quả cố định, reproducible cho báo cáo5. Tung xúc xắc / rút bài
// Tung 3 viên xúc xắc:
=INT(RAND_SEED(A1, 3) * 6) + 1
→ Mỗi seed cho kết quả khác nhau (1-6)So Sánh RAND vs Seeded RNG
Đặc điểm | RAND / RANDARRAY | Seeded RNG (LAMBDA) |
|---|---|---|
Volatile | ✅ Có — thay đổi liên tục | ❌ Không — ổn định |
Reproducible | ❌ Không | ✅ Có — cùng seed = cùng kết quả |
Hiệu năng | Chậm (tính lại liên tục) | Nhanh (chỉ tính khi seed đổi) |
Yêu cầu | Mọi phiên bản Excel | Excel 365 (LAMBDA, SCAN) |
Câu Hỏi Thường Gặp (FAQ)
Seed nên là số gì?
Bất kỳ số nguyên dương nào. Phổ biến: dùng ngày (ví dụ 20240315 cho ngày 15/3/2024), hoặc mã nhóm, hoặc bất kỳ số nào bạn muốn ghi nhớ.
Có thể tạo seeded RNG không cần LAMBDA?
Có, bằng cách dùng cột phụ (mỗi ô tham chiếu ô phía trên qua công thức LET + MOD). Tuy nhiên LAMBDA + SCAN gọn hơn nhiều và không cần cột phụ.
Kết quả có thực sự ngẫu nhiên không?
Đây là pseudo-random — giả ngẫu nhiên. Thuật toán Park-Miller đã được kiểm chứng toán học và đủ tốt cho hầu hết ứng dụng thực tế (chia nhóm, lấy mẫu, mô phỏng). Không dùng cho mật mã học.
Tổng Kết
Seeded RNG giải quyết bài toán mà RAND/RANDARRAY không làm được: tạo số ngẫu nhiên ổn định, có thể tái tạo, chỉ đổi khi bạn muốn. Chỉ cần 1 công thức LAMBDA + SCAN với thuật toán Park-Miller, bạn có hàm RAND_SEED mạnh mẽ dùng cho chia nhóm, lấy mẫu, mô phỏng, và A/B testing.
Bình luận
Đăng nhập để tham gia bình luận
Đăng nhậpNhận bài viết mới nhất
Đăng ký để nhận thông báo khi có bài viết mới. Không spam, chỉ kiến thức chất lượng.
Bài viết liên quan
Khám phá thêm các bài viết cùng chủ đề
