【C++基于中心极限定理生成高斯随机数(高斯白噪声)】

C++基于中心极限定理生成高斯随机数(高斯白噪声)

前言

在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 2151(单精度浮点数)或 2 31 − 1 2^{31}-1 2311(双精度浮点数)。假设 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) XE(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=12n Ai=1nXi21A=A1n12 i=1nXi3n (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,验证正确。
在这里插入图片描述

  • 39
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值