问我需要一个随机数生成器。
答标准 C 库有一个rand函数。您系统上的实现可能不完美,但要编写一个更好的实现也并非易事。
如果您确实需要实现自己的随机数生成器,市面上有大量相关文献;请参阅下面的参考文献或 sci.math.num-analysis FAQ 列表。网上也有不少软件包:老牌的有 r250、RANLIB 和 FSULTRA(见问题 18.16),还有 Marsaglia 以及 Matumoto 和 Nishimura(“Mersenne Twister”)的许多近期工作,以及 Don Knuth 在其 网页上收集的一些代码。
这里是 Park 和 Miller 提出的“最小标准”生成器的可移植 C 实现
#define a 16807 #define m 2147483647 #define q (m / a) #define r (m % a) static long int seed = 1; long int PMrand() { long int hi = seed / q; long int lo = seed % q; long int test = a * lo - r * hi; if(test > 0) seed = test; else seed = test + m; return seed; }(“最小标准”已足够好;它是“所有其他生成器都应与之比较的标准”;建议“除非您能获得一个*已知*更好的随机数生成器”,否则都应使用它。)
此代码实现的是生成器
X <- (aX + c) mod m其中 a = 16807, m = 2147483647(即 231-1),c = 0。[脚注] 乘法采用 Schrage 描述的技术实现,确保中间结果 aX 不会溢出。上述实现返回long int值,范围为 [1, 2147483646];也就是说,它对应 C 的rand并且RAND_MAX值为 2147483646,*除了*它从不返回 0。要将其修改为返回范围 (0, 1) 内的浮点数(如 Park 和 Miller 的论文所述),请将声明更改为
double PMrand()并将最后一行更改为
return (double)seed / m;为了获得稍好的统计特性,Park 和 Miller 现在建议使用 a = 48271。
参考文献:K&R2 第 2.7 节 第 46 页,第 7.8.7 节 第 168 页
ISO 第 7.10.2.1 节
H&S 第 17.7 节 第 393 页
PCS 第 11 章 第 172 页
Knuth 第二卷 第三章 第 1-177 页
Park 和 Miller,“随机数生成器:好的很难找到”