这应该不会太困难,但由于某种原因,这个分布中的抽样随机数实际上是在绊倒我。
我知道从分发中生成随机数的最佳选择是boost / C ++ 11库...遗憾的是,我无法使用c ++ 0x编译此代码,无论如何,我最好保留兼容我正在使用的服务器,运行gcc 4.1.2 - 古代,我知道,不支持更新的C ++。挫折。和往常一样,时间紧迫意味着我需要尽快做到最好。快速修复。
从框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()开始,然后调用:
编辑 - 我注意到它实际上调用了函数来查找对数正态参数。添加。
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
我想让lognormal std成为我想要的是什么?
其他选项也会受到赞赏 - 也许还有其他我想念的东西。
提前致谢!
编辑 - 我意识到我应该明确表示我需要从对数正态分布中进行采样