การสร้างสุ่มตัวเลขใน C++ พัฒนาขึ้นมาอย่างมาก จาก C-style rand() ไปสู่ Modern C++ <random> Library (C++11) ที่ให้ Distribution, Engine และ Quality ที่ดีกว่ามาก
1. Legacy: rand() + srand() (C-style)
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr)); // Seed ด้วยเวลา
int max = 100;
std::cout << "Random: " << (std::rand() % max) << '\n'; // 0-99
}
ข้อเสียร้ายแรง
- Low Quality Randomness (LCG Algorithm)
- Modulo Bias (
% maxทำให้ Distribution เฉี้ยว) - Global State (Thread-Unsafe)
- Range Hardcoded (RAND_MAX มัก 32767)
2. Modern C++: <random> Library (แนะนำ)
แยกเป็น 2 ส่วน: Engine (Generate Bits) และ Distribution (Map เป็น Range/Type)
Engine ที่แนะนำ
std::mt19937(Mersenne Twister 32-bit) - Standard Choicestd::mt19937_64(64-bit)std::random_device- Non-deterministic (Hardware/OS Entropy) ใช้ Seed เท่านั้น
Distribution ที่พบบ่อย
| Distribution | ใช้สำหรับ | Range |
|---|---|---|
uniform_int_distribution<T> | Integer แบบ Uniform | [a, b] Inclusive |
uniform_real_distribution<T> | Float แบบ Uniform | [a, b) หรือ [a, b] |
normal_distribution<T> | Normal (Gaussian) | Mean, StdDev |
bernoulli_distribution | Boolean (Coin Flip) | Probability p |
poisson_distribution<T> | Poisson | Mean |
ตัวอย่างสมบูรณ์ (Best Practice)
#include <random>
#include <iostream>
#include <vector>
int main() {
// 1. Seed Engine ด้วย random_device (Non-deterministic)
std::random_device rd;
std::mt19937 gen(rd()); // Engine
// 2. Define Distributions
std::uniform_int_distribution<> dice(1, 6); // ทอยเต๋า 1-6
std::uniform_real_distribution<> prob(0.0, 1.0); // Float 0-1
std::normal_distribution<> dist(5.0, 2.0); // Normal μ=5, σ=2
// 3. Generate
std::cout << "Dice rolls: ";
for (int i = 0; i < 10; ++i) std::cout << dice(gen) << ' ';
std::cout << '\n';
std::cout << "Random floats: ";
for (int i = 0; i < 5; ++i) std::cout << prob(gen) << ' ';
std::cout << '\n';
// 4. Reproducible Seed (สำหรับ Testing/Debug)
std::mt19937 gen_fixed(42); // Fixed Seed
std::cout << "Fixed seed: " << dice(gen_fixed) << '\n';
return 0;
}
Thread Safety
แต่ละ Thread ควรมี Engine ตัวเอง (Thread-Local Storage):
thread_local std::mt19937 thread_gen(std::random_device{}());
int random_int(int min, int max) {
std::uniform_int_distribution<> dist(min, max);
return dist(thread_gen);
}
Performance Tips
- Reuse Engine และ Distribution Object (อย่าสร้างใหม่ใน Loop)
- ใช้
std::uniform_int_distributionแทน%เพื่อหลีกเลี่ยง Modulo Bias - สำหรับ Cryptography: ใช้
std::random_deviceโดยตรง หรือ Crypto Library (OpenSSL, libsodium)
สรุป
ห้ามใช้ rand() ในโค้ด Modern C++ ใช้ <random> แทน: std::mt19937 + std::uniform_int_distribution ให้ Quality, Flexibility, Thread-Safety และ Standard Compliance ที่ดีที่สุด