rand() 每次运行结果相同是因为未调用 srand() 初始化种子,默认种子为1;生成[1,6]范围整数应避免 rand()%6+1 的偏差,推荐丢弃法或 c++11 的 std::mt19937 配 uniform_int_distribution。

为什么 rand() 生成的“随机数”每次运行都一样
因为没调用 srand() 初始化种子,rand() 默认用 1 当种子,结果必然固定。这不是 bug,是 C 标准规定的行为。
- 必须在程序开头(比如
main()第一行)调用srand(time(nullptr))—— 注意time(nullptr)需要#include <ctime></ctime> - 别在循环里反复调
srand(),尤其别用clock()或短周期值,反而会让序列更糟 - Windows 下
time(nullptr)只精确到秒,如果程序秒级内多次启动,仍可能撞上相同种子
怎么用 rand() 生成指定范围的 int(比如 [1, 6])
直接取模 rand() % 6 + 1 看似简单,但会引入偏差:因为 RAND_MAX 通常不是 6 的整倍数,小余数对应的结果概率略高。
- 安全写法是丢弃超出均匀区间的部分:
int r; do { r = rand(); } while (r >= RAND_MAX - RAND_MAX % 6); return r % 6 + 1; - 实际项目中,除非对统计质量敏感,多数场景
rand() % N + low足够用 —— 但得清楚它不严格均匀 -
RAND_MAX至少是 32767(C 标准下限),但具体值依赖实现,可用cout 查看
C++11 后该用什么替代 rand()
rand() 是 C 遗留接口,状态隐式全局、不可重入、分布控制弱,C++11 起应优先用 <random></random>。
- 基础组合:用
std::mt19937引擎配std::uniform_int_distribution<int></int>,例如std::mt19937 gen{std::random_device{}()}; std::uniform_int_distribution<int> dist(1, 6); int dice = dist(gen); -
std::random_device用于真随机种子,但在某些平台(如 MinGW)可能退化为常量,可 fallback 到std::chrono::steady_clock时间戳 - 引擎实例(
gen)建议复用,不要每次生成都新建 —— 构造开销大,且重复构造可能因时间太近导致种子相似
编译时发现 rand 未声明或链接失败
常见于忘记包含头文件,或混用 C/C++ 标准库命名空间。
立即学习“C++免费学习笔记(深入)”;
- 必须加
#include <cstdlib></cstdlib>(不是<stdlib.h></stdlib.h>),否则rand()和srand()不可见 - 使用
std::rand()更稳妥,避免宏污染或 ADL 干扰;但若用了using namespace std;,可能意外匹配到其他同名函数 - 在 C++23 中
rand()已被标记为 deprecated,新项目禁用是迟早的事
用 std::mt19937 + std::uniform_int_distribution 生成整数时,引擎的生命周期和复用方式比分布对象更重要——很多人只记得换分布,却把引擎当临时变量建了又扔。










