我正在寻找一种简单的算法,如何仅使用 ANSI rand() 函数但具有任意概率分布来生成伪随机浮点数。对于简单的均匀分布,我使用以下代码:
x = (float)rand() / (float)RAND_MAX;
当然不是很准确,但足以满足我的需求。我还需要其他分布,如逻辑和高斯分布。理想情况下,我必须使用有限长度的简单向量定义任意pdf,例如,对于逻辑pdf,此向量可能如下所示:
logistic_pdf = {0., 0.26894, 0.33924, 0.41742, 0.5, 0.58257, 0.66075, 1.};
对于均匀(使用相同的维度 8):
uniform_pdf = {0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125};
这只是一个想法。但我不确定如何仅使用 rand()->{0...RAND_MAX}
有效地实现它。
没有简单的算法可以做任意复杂的事情。 你必须找到每个"Arbirary"分布的逆概率积分变换。
任意离散分布,有一个线性时间初始化常量时间采样算法:
http://web.eecs.utk.edu/~vose/Publications/random.pdf
看看吧!这是非常聪明的,一点也不难实现。
你的问题没有一个简单的答案。 Luc Devroye花了800多页在他的文本"非均匀随机变量生成"中非常全面地解决了这个问题。
看看这个链接。下面是泊松分布的示例:
#include < stdlib.h >
#include < math.h >
int Poisson ( double ev ) {
int n = 0; // counter of iterations
double em; // e^(-ev), where v is the expected value
double x; // pseudorandom number
em = exp (-ev);
x = rand() / (double) RAND_MAX; // check your C compiler docs
// for the correct constant name
while (x > em) {
n++;
x *= rand() / (double) RAND_MAX;
}
return n;
}
main () {
int i;
for (i = 0; i< 1000; i++) {
printf("new Poisson value: %dn", Poisson(.133333) );
}
}
你将不得不做一些研究,因为从每个分布中绘制伪随机值的方法会有所不同。 一个合理的起点是维基百科。 它们具有从正态/高斯分布和逻辑分布生成值的方法。 其他可能感兴趣的是指数分布,β 分布和伽马分布。
或者,如果您有一些想要复制的源数据,则可以创建您拥有的数据的直方图,并从该数据生成 CDF。 然后只需生成 X~U(0,1),并确定这对应于直方图中的哪个箱,在箱的上限和下限之间线性缩放。 这就是斯塔凡提到的逆概率积分变换方法的本质。