利用Box-Muller變換生成正態分佈的隨機數(附代碼)

       前言

       之前的文章中筆者有提到利用獨立同分布的中心極限定理生成正態分佈的隨機數,對隨機數的分佈特性要求越高,利用獨立同分布的中心極限定理生成正態分佈的隨機數的算法時間複雜度也越高,如果需要大量的正態分佈隨機數“利用獨立同分布的中心極限定理生成正態分佈的隨機數”的做法是不可取的。本文將爲大家帶來時間複雜度較低的算法——利用Box-Muller變換生成正態分佈的隨機數。If you want the proof process, please see the end of the article.

      Box-Muller變換

      設 X_{1},X_{2} 是在[0,1)上遵從均勻分佈的隨機數(生成[0,1)上遵從均勻分佈的隨機數通常使用的是梅森旋轉算法),令

Y_{1}=\sqrt{-2lnX_{1}}cos(2\pi X_{2})\, \, \, \, Y_{2}=\sqrt{-2lnX_{2}}cos(2\pi X_{1})

 

(Y_{1},Y_{2})^{T} 必然遵守二元正態分佈,即利用兩個獨立的遵從均勻分佈的隨機數得到兩個獨立的正態分佈的隨機數

定理證明過程

      設

g(x_{1},x_{2})=\sqrt{-2lnx_{1}}cos(2\pi x_{2})\, \, \, \, h(x_{1},x_{2})=\sqrt{-2lnx_{2}}sin(2\pi x_{1})

     令 y_{1}=g(x_{1},x_{2})\, \, \, \, \, \: y_{2}=h(x_{1},x_{2})

       

由概率密度函數的變換公式可得

f_{Y_{1}Y_{2}}(y_{1},y_{2})=1/\left | \partial (y_{1},y_{2})/\partial (x_{1},x_{2}) \right |f_{X_{1},X_{2}}(x_{1},x_{2})

(雅可比式的定義可以參見數學分析教材)

因爲 X_{1},X_{2}在[0,1)上遵從均勻分佈,故 f_{X_{1},X_{2}}(x_{1},x_{2})=1

通過計算雅可比式的值,可得

\partial (y_{1},y_{2})/\partial (x_{1},x_{2})=-2\pi/x_{1}

聯立(1)(2)可得

x_{1}=e^{-(y_{1}^{2}+y_{2}^{2})/2}

f_{Y_{1}Y_{2}}(y_{1},y_{2})=1/2\pi e^{-(y_{1}^{2}+y_{2}^{2})/2}​​​​​​​​​​​​​​

此式恰爲二元標準正態分佈的概率密度函數

證畢

C++實現過程

//作者cclplus 如有疑問可請聯繫作者郵箱[email protected],作者會在後續內容中進行解釋
#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(x2))*sin(2 * pi*x1);
	cout << "輸出的正態分佈的隨機數爲" << endl;
	cout << y1 << " " << y2 << endl;
	return 0;
}

利用matlab設計驗證性實驗

生成一百萬個正態分佈的函數,並對結果進行驗證

%作者cclplus 有疑問請聯繫[email protected]
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);%樣本數據在圖中用“+”顯示;如果數據來自正態分佈,則圖形顯示爲直線,而其它分佈可能在圖中產生彎曲。

 

測試結果

如果想要生成其它類型的正態分佈隨機數,可以參考我之前寫的文章,利用獨立同分布的中心極限定理生成正態分佈的隨機數

Proof process 

It is assumed that the uniformly distributed random numbers X_{1},X_{2} are obeyed on [0, 1) (the generation of [0, 1) random numbers that follow a uniform distribution is usually the Mason rotation algorithm)

assume

Y_{1}=\sqrt{-2lnX_{1}}cos(2\pi X_{2})\, \, \, \, Y_{2}=\sqrt{-2lnX_{2}}sin(2\pi X_{1})

then,  (Y_{1},Y_{2})^{T} is inevitable to follow the binary normal distribution, that is, to obtain two independent normal distribution random numbers by using two independent random numbers that follow the uniform distribution.

assume

g(x_{1},x_{2})=\sqrt{-2lnx_{1}}cos(2\pi x_{2})\, \, \, \, h(x_{1},x_{2})=\sqrt{-2lnx_{2}}sin(2\pi x_{1})

y_{1}=g(x_{1},x_{2})\, \, \, \, \, \: y_{2}=h(x_{1},x_{2})

The transformation formula of the probability density function can be used to obtain the following formula

f_{Y_{1}Y_{2}}(y_{1},y_{2})=1/\left | \partial (y_{1},y_{2})/\partial (x_{1},x_{2}) \right |f_{X_{1},X_{2}}(x_{1},x_{2})

\because X_{1},X_{2}  Uniform distribution on [0,1)

\therefore f_{X_{1},X_{2}}(x_{1},x_{2})=1

By calculating the value of the Jacobian formula, you can get

\partial (y_{1},y_{2})/\partial (x_{1},x_{2})=-2\pi/x_{1}

Calculate the above formula, you can get

x_{1}=e^{-(y_{1}^{2}+y_{2}^{2})/2}

f_{Y_{1}Y_{2}}(y_{1},y_{2})=1/2\pi e^{-(y_{1}^{2}+y_{2}^{2})/2}

The formula exactly the probability density function of the binary standard normal distribution.

Q.E.D.

 

拓展閱讀   生成0-1分佈的均勻變量

```*

#include <iostream>
using namespace std;
double rand_1(double * r) {
    int m;
    double s, u, v, ret;
    s = 65536.0;
    u = 2053.0;
    v = 13849.0;
    m = (int)(*r / s);
    *r = *r - m * s;
    *r = u * *r + v;
    m = (int)(*r / s);
    *r = *r - m * s;
    ret =*r / s;
    return ret;
}

int main()
{
    double r = 5;//種子(只有改變種子,所得隨機數組才能發生變化)
    for (int i = 0; i < 10; i++) {
        cout << rand_1(&r) << endl;
    }
}
 

```

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章