我目前正在尝试创建一个高斯随机数生成器,它会产生 0 到 1 之间的值。我一直在尝试使用下面的函数,平均值为 0,标准差为 1,但是当我通过这个函数生成随机数时循环,我最终生成的大部分值都超出了 [0,1] 的范围。我将如何调整我正在做的事情以将这些值带入该范围内?
float Network::box_muller(float m, float s) {
float x1, x2, w, y1;
static float y2;
static int use_last = 0;
if (use_last) {
y1 = y2;
use_last = 0;
}
else {
do {
x1 = 2.0 * ((double)rand() / (RAND_MAX)) - 1.0;
x2 = 2.0 * ((double)rand() / (RAND_MAX)) - 1.0;
w = x1 * x1 + x2 * x2;
} while (w >= 1.0);
w = sqrt((-2.0 * log(w)) / w);
y1 = x1 * w;
y2 = x2 * w;
use_last = 1;
}
return(m + y1 * s);
}
对于生产代码:
如果您有权访问 C++11 功能,那么您应该使用std::normal_distribution
( http://en.cppreference.com/w/cpp/numeric/random/normal_distribution ) 或其变体之一,而不是自己实现该功能。这应该给你一个健壮的(不使用rand()
)、线程安全的(你的不是)、经过良好测试的实现。
用于学习目的
维基百科在 C++ 中有一个该算法的示例实现。具体来说,我可以看到您的代码有两个问题。
您没有正确处理 的情况w==0
。即log(0)
和除以零是未定义的。
为您的更新功能y1
和y2
不正确。正确的算法(在伪代码):y1 = sqrt(-2 * log(u1)) * cos(2*PI*u2)
和y2 = sqrt(-2 * log(u1)) * sin(2*PI*u2)
其中显然u1
必须在范围(0,1),而U2是不受约束的。
也在一个次要的句法点上。您的use_last
变量应该是 a bool
,而不是int
C++ 中的an 。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句