prev up next   top/contents search

comp.lang.c FAQ 列表· 第 13.15 题

我需要一个随机数生成器。


标准 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,“随机数生成器:好的很难找到”


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管