1. 从C的rand()到C++11的:为什么面试官会皱眉
那天面试的场景我还历历在目。当面试官问及随机数生成时,我自信满满地搬出了大学课本里的经典方案:
c复制#include <stdlib.h>
#include <time.h>
int main() {
srand(time(0)); // 用时间做种子
int random_num = rand() % 100; // 0-99的随机数
// ...
}
没想到面试官听到这个回答后,直接结束了面试。后来我才明白,在C++11标准发布12年后的今天,还在用C风格的随机数生成,就像在智能手机时代炫耀自己的BP机一样不合时宜。
1.1 C风格随机数的致命缺陷
rand()函数的问题远比想象中严重。首先,它使用的是线性同余算法(LCG),这种算法生成的随机数存在明显的模式。如果你连续调用rand()生成三维坐标点,这些点会在空间中形成可见的平面图案——这在需要高质量随机数的图形学或密码学应用中是灾难性的。
更糟糕的是,rand() % N这种取模用法会引入偏差。因为RAND_MAX(通常是32767)不一定是N的整数倍,导致小数值出现的概率更高。例如当N=100时,0-67出现的概率是68/32768,而68-99的概率是67/32768。
实际测试:连续生成1亿次
rand() % 100,数值68-99的出现次数比理论值少约1.5%
1.2 C++11的随机数革命
2011年发布的C++11标准引入了<random>库,它提供了:
-
多种随机数引擎(生成原始随机数序列)
- std::mt19937:梅森旋转算法,周期长达2^19937-1
- std::minstd_rand:改进的LCG,比rand()质量高
- std::ranlux48:高延迟引擎,适合蒙特卡洛模拟
-
随机数分布器(将原始序列映射到所需分布)
- std::uniform_int_distribution:均匀整数分布
- std::normal_distribution:正态分布
- std::poisson_distribution:泊松分布
这才是现代C++应有的样
