正态分布,泊松分布,指数分布的c/c++代码


在做实验的时候,需要产生符合某种分布的随机数。

这里总结一下正态分布,泊松分布和指数分布的算法和对应c/c++代码。


# 参照算法和代码可以转换成对应的其他编程语言


正态分布


正态分布(德语:Normalverteilung;英语:normal distribution)又名高斯分布(德语:Gauß-Verteilung;英语:Gaussian distribution, 以德国数学家卡尔·弗里德里希·高斯的姓冠名),是一个在数学、物理及工程等领域都非常重要的概率分布,由于这个分布函数具有很多非常漂亮的性质,使得其在诸多涉及统计科学离散科学等领域的许多方面都有着重大的影响力。比如图像处理中最常用的滤波器类型为Gaussian滤波器(也就是所谓的正态分布函数)。


若随机变量X服从一个位置参数为\mu、尺度参数为\sigma的概率分布,记为:

java正态分布应用 正态分布函数编程_正态分布




则其概率密度函数为

java正态分布应用 正态分布函数编程_指数分布_02




常用的成熟的生成高斯分布随机数序列的方法由Marsaglia和Bray在1964年提出,C++版本如下:

#include <stdlib.h>
#include <math.h>
 
double gaussrand_NORMAL() {
	static double V1, V2, S;
	static int phase = 0;
	double X;


	if (phase == 0) {
		do {
			double U1 = (double) rand() / RAND_MAX;
			double U2 = (double) rand() / RAND_MAX;


			V1 = 2 * U1 - 1;
			V2 = 2 * U2 - 1;
			S = V1 * V1 + V2 * V2;
		} while (S >= 1 || S == 0);


		X = V1 * sqrt(-2 * log(S) / S);
	} else
		X = V2 * sqrt(-2 * log(S) / S);


	phase = 1 - phase;


	return X;
}


double gaussrand(double mean, double stdc) {
	return mean + gaussrand_NORMAL() * stdc;
}


这样生成的是标准正态分布,期望为0.0,方差为1.0。若指定期望为E,标准差为V,则只需增加:

X = X * V + E;


E(X) = E

D(X) = V * V

  


参考


http://blog.sina.com.cn/s/blog_65273bfa01013wdh.html http://blog.ch-wind.com/c%E6%AD%A3%E6%80%81%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90/


https://zh.wikipedia.org/wiki/%E6%AD%A3%E6%80%81%E5%88%86%E5%B8%83



泊松分布

泊松分布适合于描述单位时间内随机事件发生的次数的概率分布。如某一服务设施在一定时间内受到的服务请求的次数,电话交换机接到呼叫的次数、汽车站台的候客人数、机器出现的故障数、自然灾害发生的次数、DNA序列的变异数、放射性原子核的衰变数等等。


泊松分布的概率质量函数为:



一个用来生成随机泊松分布的数字(伪随机数抽样)的简单算法,已经由高德纳给出(见下文参考):


algorithm poisson random number (Knuth):
init:
   Let L ← exp(−λ), k ← 0 and p ← 1.
do:
   k ← k + 1.
   Generate uniform. random number u in [0,1] and let p ← p × u.
while p >= L.
return (k − 1).


c/c++代码:


#include <stdio.h>
#include <math.h>
#include <time.h>
 
double U_Random();
int possion();
 
 
void main()
{
        double u = U_Random();
        int p = possion();
        printf("%fn",u);
        printf("%dn",p);
 
}
 
int possion()  /* 产生一个泊松分布的随机数,Lamda为总体平均数*/
{
        int Lambda = 20, k = 0;
        long double p = 1.0;
        long double l=exp(-Lambda);  /* 为了精度,才定义为long double的,exp(-Lambda)是接近0的小数*/
        printf("%.15Lfn",l);
        while (p>=l)
        {
                double u = U_Random();
                p *= u;
                k++;
        }
        return k-1;
}
 
double U_Random()   /* 产生一个0~1之间的随机数 */
{
        double f;
        srand( (unsigned)time( NULL ) );
        f = (float)(rand() % 100);
        /* printf("%fn",f); */
        return f/100;
}

E(X) = 1 / λ

D(X) = 1 / λ / λ



参考

http://www.111cn.net/net/c/79927.htm



https://zh.wikipedia.org/wiki/%E6%B3%8A%E6%9D%BE%E5%88%86%E4%BD%88



指数分布

在概率论和统计学中,指数分配(英语:Exponential distribution)是一种连续概率分布。指数分配可以用来表示独立随机事件发生的时间间隔,比如旅客进入机场的时间间隔、打进客服中心电话的时间间隔、中文维基百科新条目出现的时间间隔等等。


一个指数分布的概率密度函数是:



其中λ > 0是分布的一个参数,常被称为率参数(rate parameter)。即每单位时间发生该事件的次数。指数分布的区间是[0,∞)。 如果一个随机变量X 呈指数分布,则可以写作:X ~ Exponential(λ)。


c/c++代码:


double cls_random::randomExponential(
    double lambda)
{
    double pV = 0.0;
    while(true)
    {
        pV = (double)rand()/(double)RAND_MAX;
        if (pV != 1)
        {
            break;
        }
    }
    pV = (-1.0/lambda)*log(1-pV);
    return pV;
}


参考




https://zh.wikipedia.org/wiki/%E6%8C%87%E6%95%B0%E5%88%86%E5%B8%83