如何按照C或C ++的正态分布轻松生成随机数?
我不希望使用Boost。
[我知道Knuth详尽地谈论了这个问题,但是我现在没有他的书。
generate Gaussian-distributed numbers from a regular RNG有很多方法。
Box-Muller transform是常用的。它会正确产生具有正态分布的值。数学很简单。您生成两个(均匀)随机数,然后对它们应用公式,就得到两个正态分布的随机数。返回一个,并将另一个保存为下一个随机数请求。
C ++ 11提供了std::normal_distribution
,这就是我今天要去的方式。
以下是按复杂度升序排列的一些解决方案:
将0到1之间的12个统一随机数相加并减去6。这将与正态变量的均值和标准差匹配。一个明显的缺点是范围限制为±6,这与真实的正态分布不同。
Box-Muller变换。这已在上面列出,并且实现起来相对简单。但是,如果您需要非常精确的样本,请注意,将Box-Muller变换与某些均匀生成器结合使用会遇到一个称为Neave Effect 1] ..
的异常现象。为了获得最佳精度,我建议绘制制服并应用逆累积正态分布以得出正态分布变量。 std::normal_distribution
是逆累积正态分布的很好算法。
1。 H. R. Neave,“将Box-Muller变换与乘法同余伪随机数生成器一起使用”,《应用统计》,22,92-97,1973
一种快速简便的方法只是求和多个均匀分布的随机数并取其平均值。请参阅Here,以获取有关其工作原理的完整说明。
我创建了一个Central Limit Theorem。
这是一个C ++示例,基于一些参考。这既快速又肮脏,最好不要重新发明并使用boost库。
使用#include "math.h" // for RAND, and rand
double sampleNormal() {
double u = ((double) rand() / (RAND_MAX)) * 2 - 1;
double v = ((double) rand() / (RAND_MAX)) * 2 - 1;
double r = u * u + v * v;
if (r == 0 || r > 1) return sampleNormal();
double c = sqrt(-2 * log(r) / r);
return u * c;
}
。
这是在现代C ++编译器上生成示例的方式。
您可以使用#include <random>
...
std::mt19937 generator;
double mean = 0.0;
double stddev = 1.0;
std::normal_distribution<double> normal(mean, stddev);
cerr << "Normal: " << normal(generator) << endl;
。一些GSL来演示如何使用它。
看一下:complete examples are given。这是产生正态分布的最简单方法。
如果使用的是C ++ 11,则可以使用http://www.cplusplus.com/reference/random/normal_distribution/:
我遵循了std::normal_distribution
中给出的PDF的定义,并提出了以下要求:
comp.lang.c FAQ列表
Box-Muller实现:
存在多种用于逆累积正态分布的算法。在http://c-faq.com/lib/gaussian.html]上测试了最受欢迎的量化金融
我认为,除了#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
using namespace std;
// return a uniformly distributed random number
double RandomGenerator()
{
return ( (double)(rand()) + 1. )/( (double)(RAND_MAX) + 1. );
}
// return a normally distributed random number
double normalRandom()
{
double y1=RandomGenerator();
double y2=RandomGenerator();
return cos(2*3.14*y2)*sqrt(-2.*log(y1));
}
int main(){
double sigma = 82.;
double Mi = 40.;
for(int i=0;i<100;i++){
double x = normalRandom()*sigma+Mi;
cout << " x = " << x << endl;
}
return 0;
}
中的算法AS241外,没有太多动机去使用其他东西:机器精度高,可靠且快速。高斯随机数生成中很少出现瓶颈。
1]可以使用类似于蒙特卡洛方法的方法直观地生成高斯随机数。您可以使用C中的伪随机数生成器在高斯曲线周围的框中生成一个随机点。您可以使用分布方程式来计算该点是在高斯分布的内部还是下方。如果该点在高斯分布内,那么您就获得了高斯随机数作为该点的x值。
蒙特卡罗方法
看看我发现了什么。
计算机是确定性设备。计算中没有随机性。此外,CPU中的算术设备可以评估一些有限的整数集(在有限域中执行评估)和有限的实有理数集。并且还执行了按位运算。数学处理了很多更出色的集合,例如[0.0,1.0],并且具有无限的点数。