这应该不会太难,但出于某种原因,这种从分布中抽样随机数真的让我很吃惊。
我知道从发行版生成随机数的最佳选择是 boost/C++11 库...不幸的是,我无法使用 c++0x 编译此代码,无论如何,我最好保持兼容性我也在使用的服务器,它正在运行 gcc 4.1.2 - 我知道,古老的不支持较新的 C++。挫折。和往常一样,时间紧迫意味着我需要尽我所能快速修复。
从 box muller 方程中获取随机数的指数是我的下一个选择,但我没有得到带有我指定参数的对数正态分布。我不明白为什么这不起作用。
任何帮助将不胜感激!
void testRNG(){
int mean = 5000;
int std = 50;
ofstream out("./Output/normal_samples.out");
RunningStats normal;
for (int i=0;i<2000;++i){
double sample = randomSample(mean, std, NORMAL);//call function with box muller transformation to return a number from a normal distriubtion
out<<sample<<endl;
normal.Push(sample);//keep a running average of sampled numbers
}
cout<<"Normal Mean = "<<normal.Mean()<<endl;
cout<<"Normal Std = "<<normal.StandardDeviation()<<endl;
RunningStats lognormal;
for (int i=0;i<2000;++i){
double sample = randomSample(mean, std, LOGNORMAL);
out<<sample<<endl;
lognormal.Push(sample);
}
cout<<"Lognormal Mean = "<<lognormal.Mean()<<endl;
cout<<"Lognormal Std = "<<lognormal.StandardDeviation()<<endl;
}
采样函数,我没有写,首先从 randomSample() 到一个 case,然后调用:
编辑 - 我注意到它实际上确实调用了一个函数来查找对数正态参数。添加进来。
double randNormal(double mean, double stdev) {
static long numSamples = 0;
static double Z2;
if ((numSamples++ & 1) == 0) {
double Z1, U1, U2;
do { U1 = randUniform(0, 1); } while (U1 <= 0 || U1 >= 1);
do { U2 = randUniform(0, 1); } while (U1 <= 0 || U1 >= 1);
Z1 = sqrt(-2 * log(U1)) * cos(6.28318531 * U2);
Z2 = sqrt(-2 * log(U1)) * sin(6.28318531 * U2);
return mean + stdev * Z1;
} else {
return mean + stdev * Z2;
}
}
double randLognormal(double mu, double sigma) {
return exp(randNormal(mu, sigma));
}
double randLognormalMeanStdev(double mean, double stdev) {
return randLognormal( log(mean) - 0.5 * log(1 + (stdev * stdev) / (mean * mean)) , log(1 + (stdev * stdev) / (mean * mean)));
}
所以我得到的输出是:
Normal Mean = 4998.72 //I said 5000
Normal Std = 49.7054 //I said 50
Lognormal Mean = 4999.74
Lognormal Std = 0.492766 //this is the part that is not working
为了使对数正态标准成为我想要的,我缺少什么?
其他选择也将不胜感激-也许我还缺少其他东西。
提前致谢!
编辑 - 我意识到我应该明确表示我需要从对数正态分布中采样