我正在尝试通过使用极坐标以及均值和西格玛值来生成两个标准正态变量r1,r2来生成随机变量。然而,当我运行我的代码时,我不断得到一个" -nan(ind)"作为我的输出。
我在这里做错了什么?代码如下:
static double saveNormal;
static int NumNormals = 0;
static double PI = 3.1415927;
double fRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
static double normal(double r, double mean, double sigma) {
double returnNormal;
if (NumNormals == 0) {
//to get next double value
double r1 = fRand(0, 20);
double r2 = fRand(0, 20);
returnNormal = sqrt(-2 * log(r1)) * cos(2 * PI*r2);
saveNormal = sqrt(-2 * log(r1)) * sin(2 * PI*r2);
}
else {
NumNormals = 0;
returnNormal = saveNormal;
}
return returnNormal*sigma + mean;
}
答案 0 :(得分:3)
因此,您正在使用 Box-Muller 方法伪随机采样正常的随机变量。要使此转换起作用,r1
和r2
必须在[0,1]中均匀分布独立变量。
相反,您的r1/r2
支持[0,20],当> 1时会产生负sqrt
参数,这将为您提供nans。替换为
double r1 = fRand(0, 1);
double r2 = fRand(0, 1);
此外,您应该使用C ++ 11 <random>
来生成更好的伪随机数;截至目前,由于fRand
- 至 - rand()
转换以及相邻电话之间可能存在虚假关联,您的double
质量较差。此外,您的函数缺少一些基本的错误检查,严重依赖于全局变量,并且本质上是线程不安全。
仅供参考,这是C ++ 11版本的样子
#include <random>
#include <iostream>
int main()
{
auto engine = std::default_random_engine{ std::random_device{}() };
auto variate = std::normal_distribution<>{ /*mean*/0., /*stddev*/ 1. };
while(true) // a lot of normal samples ...
std::cout << variate(engine) << std::endl;
}
答案 1 :(得分:1)