我很难保持随机生成的值,这些值正态分布在0和1之间(包括0,不包括1)。我相信算法基本上是正确的,我只是被难住了。任何见解都会很棒。
这些是所需的包括文件:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
正态分布随机数生成器函数:
float rand_normal(float mean, float stddev)
{
static float n2 = 0.0;
float x, y, r;
static int n2_cached = 0;
if (!n2_cached)
{
do
{
x = 2.0*rand()/RAND_MAX - 1;
y = 2.0*rand()/RAND_MAX - 1;
r = x*x + y*y;
} while (r==0.0 || r>1.0);
float d = sqrt(-2.0*log(r)/r);
float n1 = x*d;
float result = n1*stddev + mean;
n2 = y*d;
n2_cached = 1;
return result;
}
else
{
n2_cached = 0;
return n2*stddev + mean;
}
}
主要功能仅用于测试目的。
int main()
{
srand(time(NULL));
int i;
float min = 0.5, max = 0.5, r, avg = 0;
float x, w;
int n = 10000000;
for (i=0; i<n; i++)
{
r = rand_normal(0.5, 0.09);
if (r < min)
min = r;
else if ( r>max)
max = r;
avg += r;
}
avg /= (float)n;
printf("min = %fnmax = %fnavg = %fn", min, max, avg);
return 0;
}
如果有人想知道,这个功能是"植物遗传"模拟所必需的。
为什么希望结果保持在0和1之间?高斯分布得到了充分的支持,所以无论你观察的区间是什么,无论你选择的均值和方差是什么,都会有(可能性很小)非零概率超出该区间。如果出于某种原因,你真的想把自己限制在[0,1],那么你可以简单地调用rand_normal,直到你陷入这个区间。
还要注意的是,虽然Box-Müller(您正在使用的算法)很容易实现,但这是生成高斯随机变量最糟糕、成本最高的方法之一。我所知道的最好、最快的算法是"Ziggurat"方法,它的实现可以在中找到
http://www.seehuhn.de/pages/ziggurat
我肯定会创建一个函数来将"rand()"转换为标准化的浮点值。例如:
double
nrand ()
{
return rand()/(RAND_MAX - 1);
}
此外,这里有一些链接可能会有所帮助:
http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx
http://people.sc.fsu.edu/~jburkardt/c-src/normal/normal.html