利用Box-Muller变换生成正态分布的随机数
程序员文章站
2024-03-25 21:36:16
...
前言
之前的文章中笔者有提到利用独立同分布的中心极限定理生成正态分布的随机数,对随机数的分布特性要求越高,利用独立同分布的中心极限定理生成正态分布的随机数的算法时间复杂度也越高,如果需要大量的正态分布随机数“利用独立同分布的中心极限定理生成正态分布的随机数”的做法是不可取的。本文将为大家带来时间复杂度较低的算法——利用Box-Muller变换生成正态分布的随机数。
Box-Muller变换
设是在[0,1)上遵从均匀分布的随机数(生成[0,1)上遵从均匀分布的随机数通常使用的是梅森旋转算法),令
则必然遵守二元正态分布,即利用两个独立的遵从均匀分布的随机数得到两个独立的正态分布的随机数
定理证明过程
设
令
由概率密度函数的变换公式可得
(雅可比式的定义可以参见数学分析教材)
因为是在[0,1)上遵从均匀分布的随机数,故
通过计算雅可比式的值,可得
联立(1)(2)可得
故
此式恰为二元标准正态分布的概率密度函数
证毕
C++实现过程
//作者cclplus 如有疑问可请联系作者邮箱aaa@qq.com,作者会在后续内容中进行解释
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
const double pi = 3.1415926897932384;
int main() {
ios::sync_with_stdio(false);
double x1, x2,y1,y2;
int seed;//手动输入种子
cout << "手动输入种子(任意给出一个整数)" << endl;
cin >> seed;
srand(seed);
x1 = rand()% RAND_MAX /(double) RAND_MAX;
x2= rand() % RAND_MAX / (double)RAND_MAX;
cout << "产生的均匀分布的随机数种子为" << endl;
cout << x1 <<" "<< x2 << endl;
y1 = sqrt(-2 * log(x1))*cos(2 * pi*x2);
y2 = sqrt(-2 * log(x1))*sin(2 * pi*x2);
cout << "输出的正态分布的随机数为" << endl;
cout << y1 << " " << y2 << endl;
return 0;
}
利用matlab设计验证性实验
生成一百万个正态分布的函数,并对结果进行验证
%作者cclplus 有疑问请联系aaa@qq.com
clc
clear all
close all
n=1000000;
x1=rand(n,1);
x2=rand(n,1);
y1=sqrt(-2.*log(1.*x1)).*cos(2*pi.*x2);%生成正态分布函数
figure;
normplot(y1);%样本数据在图中用“+”显示;如果数据来自正态分布,则图形显示为直线,而其它分布可能在图中产生弯曲。
测试结果
如果想要生成其它类型的正态分布随机数,可以参考我之前写的文章,利用独立同分布的中心极限定理生成正态分布的随机数