前言
在c++的标准头文件中,‘math.h’并没有直接提供高斯随机数的生成函数。‘math.h’头文件主要包含了数学函数和常量的声明,例如三角函数、对数函数和指数函数等。要生成高斯随机数,你可以使用c++标准库中一个名为‘rand()’的函数,可以用于生成伪随机数,这个函数在‘<stdlib.h>’头文件中声明。生成的伪随机数服从均匀分布,通过采样足够多的样本,依据中心极限定理便可得到高斯随机数。
中心极限定理
中心极限定理是概率论中的一个重要的定理,它描述了当从任意分布中抽取大量样本时,样本均值的分布将近似服从于正态分布。
生成算法
高斯随机数又可以称为高斯白噪声,它是一种最为随机的噪声,存在于许多自然或工程领域中。首先定义rand(A)函数表示为能够产生在区间
[
0
,
A
]
[0,A]
[0,A]上的一个随机值的随机数发生器,它在该区间上满足均匀分布。一般区间右边界
A
A
A的值可取
2
15
−
1
2^{15}-1
215−1(单精度浮点数)或
2
31
−
1
2^{31}-1
231−1(双精度浮点数)。假设
X
X
X是一个随机数,将随机变量
X
X
X进行归一化可以构造出随机变量
Z
Z
Z:
Z
=
X
−
E
(
X
)
V
a
r
(
X
)
(
1
)
Z=\frac{X-E(X)}{\sqrt{Var(X)}}\qquad(1)
Z=Var(X)X−E(X)(1)
式(1)中,
E
(
X
)
E(X)
E(X)为
X
X
X的数学期望,
V
a
r
(
X
)
Var(X)
Var(X)为
X
X
X的方差。假设对任意
i
=
1
,
.
.
.
,
n
i=1,...,n
i=1,...,n,
X
i
X_i
Xi均在区间
[
0
,
A
]
[0,A]
[0,A]上服从均匀分布,因此有:
E
(
X
i
)
=
1
2
A
(
2
)
E(X_i)=\frac{1}{2}A\qquad(2)
E(Xi)=21A(2)
V
a
r
(
X
i
)
=
1
12
A
2
(
3
)
Var(X_i)=\frac{1}{12}A^2\qquad(3)
Var(Xi)=121A2(3)
E
(
∑
i
=
1
n
X
i
)
=
n
2
A
(
4
)
E(\sum_{i=1}^nX_i)=\frac{n}{2}A\qquad(4)
E(∑i=1nXi)=2nA(4)
V
a
r
(
∑
i
=
1
n
X
i
)
=
n
2
A
2
(
5
)
Var(\sum_{i=1}^nX_i)=\frac{n}{2}A^2\qquad(5)
Var(∑i=1nXi)=2nA2(5)
通过概率论中心极限定理生成服从高斯噪声的随机数。生成过程如下:对于公式(1),假设
X
X
X是由
n
n
n个具有相同分布的随机变量相加得到的结果,记为
X
=
∑
i
=
1
n
X
i
X=\sum_{i=1}^nX_i
X=∑i=1nXi,当随机变量的样本足够大时,即
n
→
∞
n\rightarrow\infty
n→∞,公式(1)中随机变量
Z
Z
Z服从均值为0,方差为1的高斯分布。把服从高斯分布的随机变量记为
Z
n
Z_n
Zn,
Z
n
=
∑
i
=
1
n
X
i
−
1
2
A
n
12
A
=
1
A
12
n
∑
i
=
1
n
X
i
−
3
n
(
6
)
Z_n=\frac{\sum_{i=1}^nX_i-\frac{1}{2}A}{\sqrt{\frac{n}{12}}A}=\frac{1}{A}\sqrt{\frac{12}{n}}\sum_{i=1}^{n}X_i-\sqrt{3n}\qquad(6)
Zn=12nA∑i=1nXi−21A=A1n12i=1∑nXi−3n(6)
c++代码实现
代码需要包含如下头文件
#include <iostream>
#include <cstdlib>
#include<vector>
using namespace std;
生成高斯噪声代码
double generateGaussianNoise() {
double Sum = 0.0;
int numSample = 1000; // 采样个数
for (int i = 0; i < numSample; i++) {
Sum += static_cast<double>(rand());
}
// 公式(6)
double Res = (Sum - numSample / 2.0 * RAND_MAX) / (sqrt(numSample / 12.0) * RAND_MAX);
return Res;
}
主函数
int main() {
for (int i = 0; i < 1000; ++i) {
double sample = generateGaussianNoise();
cout << "Sample " << i << ": " << sample << endl;
}
return 0;
}
验证结果
利用generateGaussianNoise()生成多个随机数,求取其均值和方差,看其是否为0和1。
计算均值
double cal_mean(vector<double> val) {
double length = static_cast<double>(val.size());
double Sum = 0.0;
for (double num : val)
Sum += num;
return Sum / length;
}
计算方差
double cal_Var(vector<double> val) {
double length = static_cast<double>(val.size());
double mean = cal_mean(val);
double Sum = 0.0;
for (double num : val)
Sum += pow(num - mean, 2);
return Sum / length;
}
主函数
int main() {
vector<double> Res;
for (int i = 0; i < 1000; ++i) {
double sample = generateGaussianNoise();
Res.push_back(sample);
cout << "Sample " << i << ": " << sample << endl;
}
double mean = cal_mean(Res);
double var = cal_Var(Res);
cout << "mean: " << mean << endl;
cout << "var: " << var << endl;
return 0;
}
打印结果,其均值接近0,方差接近1,验证正确。