rand() 已过时,因周期短、分布不均、低位随机性差、跨平台行为不一致;应改用 中的 std::mt19937 配合 std::uniform_*_distribution 和 std::random_device 种子。
rand() 不该再用了因为它的周期短、分布不均、低比特位随机性差,且在不同平台行为不一致。比如 rand() % 10 会明显偏向小数字,RAND_MAX 在 Windows 是 32767,Linux 可能是 2147483647,直接导致可移植性崩坏。
rand() 为“legacy”,C++17 起建议用
std::mt19937 是梅森旋转的 C++ 标准封装std::mt19937 就是梅森旋转算法(Mersenne Twister)的 32 位实现,周期为 2¹⁹⁹³⁷−1,通过了 Diehard 和 TestU01 大量统计检验。它不是“伪随机数生成器”(PRNG)的泛称,而是特指这个具体算法。
std::random_device,否则每次运行都一样time(nullptr) 初始化——秒级精度太粗糙,多进程下极易重复std::mt19937_64 提供 64 位输出,适合需要大范围整数或更高精度的场景std::random_device rd; // 真随机种子源(通常读取 /dev/urandom 或 CryptGenRandom) std::mt19937 gen(rd()); // 用真种子初始化 mt19937 std::uniform_int_distributiondist(1, 100); // [1, 100] 均匀整数分布 int x = dist(gen); // 每次调用生成一个高质量随机数
std::uniform_real_distribution 才是生成浮点随机数的正确方式别再写 (double)rand() / RAND_MAX。它既不均匀,也不能控制区间开闭,还受 RAND_MAX 限制。C++ 的分布类才是唯一可控、可验证、可重播的方案。
std::uniform_real_distribution 生成 [a, b) 区间的浮点数(左闭右开),不是四舍五入近似std::nextafter(b, std::numeric_limits::max()) 扩展上界
operator() 是内联函数,编译器可完全优化std::mt19937 gen(std::random_device{}());
std::uniform_real_distribution dist(0.0, 1.0); // [0.0, 1.0)
double r = dist(gen); // 真正均匀、可重现、符合 IEEE 754
std::mt19937 实例std::mt19937 本身不是线程安全的——内部状态修改(如 gen())没有原子保护。多个线程并发调用会破坏状态,导致输出重复、崩溃或未定义行为。
std::mt19937 实例(用不同种子初始化)thread_local static std::mt19937 gen{std::random_device{}()}; —— 首次访问才初始化,且每个线程独享梅森旋转虽快,但反复构造分布对象(如每次调用都 new 一个 uniform_int_distribution)反而成为瓶颈。分布对象应复用,生成器状态才是关键资源。