为何调用srand(time(NULL))后首次rand()输出随运行递增?
问题解答:srand(time(NULL))后首次rand()结果稳步递增的现象
这是macOS(及BSD类系统)下rand()实现的已知特性,并非bug,和它采用的线性同余生成器(LCG)初始化逻辑直接相关。
原因分析
macOS的rand()使用经典的线性同余算法,核心公式大致为:
next = (a * current + c) % m
其中a、c、m是固定常数(BSD系中通常取a=1103515245,c=12345,m=2^31)。调用srand(seed)时,生成器的初始current值会被设置为seed。
首次调用rand()时,直接计算(a * seed + c) % m并返回结果。由于你用time(NULL)作为种子——它返回的是秒级递增的时间戳,每次运行程序的种子值稳步上升,代入公式后,首次rand()的结果自然会呈现明显的线性递增趋势。
而第二次调用rand()时,是基于第一次的结果作为新的current值计算,此时已经脱离了原始种子的直接线性关联,结果就会恢复到看似随机的状态。
解决/优化方案
如果需要首次调用的随机数也具备更好的随机性,可以采用以下两种方式:
- 在
srand()之后先调用几次rand()并丢弃结果,示例:srand(time(NULL)); rand(); // 丢弃第一个结果 printf("%d\n", rand()); // 此时输出随机性更符合预期 - 改用C++11及以上标准提供的现代随机数库(推荐),比如
std::mt19937,示例代码:#include <cstdio> #include <random> #include <ctime> int main() { std::mt19937 rng(time(NULL)); printf("%d\n", (int)rng()); printf("%d\n", (int)rng()); return 0; }
附用户提供的测试信息
测试代码
#include <cstdio> #include <cstdlib> #include <ctime> using namespace std; int main() { srand(time(NULL)); printf("%d\n", rand()); printf("%d\n", rand()); return 0; }
Makefile
BINARIES := test all: $(BINARIES) clean: $(RM) $(BINARIES) *~ *.dSYM CXXFLAGS := -Wall -g -std=gnu++11 -O3 CXX := g++ RM := rm -r
8次运行输出
➜ Coding ./test 830930336 360000711 ➜ Coding ./test 830963950 924951209 ➜ Coding ./test 830980757 1207426458 ➜ Coding ./test 831014371 1772376956 ➜ Coding ./test 831064792 472319056 ➜ Coding ./test 831081599 754794305 ➜ Coding ./test 831098406 1037269554 ➜ Coding ./test 831115213 1319744803
内容的提问来源于stack exchange,提问作者Shen-Fu Tsai
相关产品推荐
相关产品推荐

