为何C语言srand()函数在Windows与Linux下行为存在差异?
平台差异:连续递增种子下rand()输出规律不同的原因
当用死循环每次以递增1秒的时间戳(time(NULL))重置随机种子srand(),生成首个随机数后休眠1秒时,Windows平台(MinGW-W64的gcc/clang、MSVC运行时)生成的首个随机数会连续递增,而Linux平台无此规律。Lua 5.1这类基于C标准库随机数实现的语言也存在同样问题。已知这种每次重置种子的用法不规范,下面解释平台差异的核心原因。
测试代码
#include<time.h> #include<stdlib.h> #include<stdio.h> #ifdef __linux__ #include <unistd.h> #else #include <windows.h> #endif void printRandoms(int lower, int upper, int count) { int i; for (i = 0; i < count; i++) { int num = (rand() % (upper - lower + 1)) + lower; printf("%d\n", num); } } int main(){ while(1){ srand(time(NULL)); printRandoms(1,10000,1); #ifdef __linux__ sleep(1); #else Sleep(1000); #endif } return 0; }
测试输出结果
Windows平台(测试编译器:MinGW-W64 gcc 13.1.0/9.5.0、clang 16.0.5)
5237 5238 5239 5240 5241 5242 5243 5245 5246 5247 5248
Linux平台(测试编译器:Ubuntu gcc 9.4.0)
5142 3660 7270 896 9500 3041 6659 5194 8809 7361 5960
平台差异原因
Windows平台rand()实现特性:Windows系统(包括MinGW依赖的MSVCRT/UCRT运行时)的
rand()采用线性同余生成器(LCG),且首次调用rand()时直接返回种子代入LCG公式的结果。LCG公式为next = (a * seed + c) % m,Windows使用的参数(如MSVCRT的a=214013, c=2531011, m=2^31)使得当种子连续+1时,首次输出结果会按固定步长线性递增,呈现连续上升的规律。Linux平台rand()实现特性:Linux glibc的
rand()虽基于LCG,但对初始种子做了额外处理。它不会直接返回LCG的初始计算值,而是将种子经过多轮迭代变换后再输出第一个随机数,或者对初始种子进行了混淆操作,导致连续递增的种子对应的首次输出不再呈现线性相关的规律,看起来更无规律。
内容的提问来源于stack exchange,提问作者Bubbleioa
相关产品推荐
相关产品推荐

