1. 程式人生 > >使用rand()產生服從高斯/正態分佈的隨機數

使用rand()產生服從高斯/正態分佈的隨機數

我們藉助於rand()去生成高斯/正態分佈。

當然,rand是偽隨機的問題在此先不考慮。

(1)用Box-Muller方法,隨機抽出兩個從[0,1]均勻分佈的數字uv。然後

z_1 = \sqrt{-2 \log u} \cos 2\pi v z_2 = \sqrt{-2 \log u} \sin 2\pi vz_1z_2都是正態分佈的。
證明可用極座標,請參考教科書中的Box-Muller方法。

C程式碼:

#include <stdlib.h>
#include <stdio.h>
#define PI 3.141592654double 
  double gaussrand( )
{
    static double U, V;
    static int phase = 0;
    double z;

    if(phase == 0)
    {
         U = rand() / (RAND_MAX + 1.0);
         V = rand() / (RAND_MAX + 1.0);
         Z = sqrt(-2.0 * log(U))* sin(2.0 * PI * V);
    }
    else
    {
         Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V);
    }

    phase = 1 - phase;
    retrn Z;
}

這樣生成的高斯分佈隨機數序列的期望為0.0,方差為1.0。若指定期望為E,方差為V,則只需增加:
 X= X * V + E;

Python程式碼:

import numpy as np
from scipy.special import erfinv

def boxmullersampling(mu=0, sigma=1, size=1):
    u = np.random.uniform(size=size)
    v = np.random.uniform(size=size)
    z = np.sqrt(-2*np.log(u))*np.cos(2*np.pi*v)
    return mu+z*sigma

(2)使用反函式,先隨機抽出一個從[0,1]均勻分佈的數字u,然後

z=\sqrt{2} \text{erf}^{-1}(2u-1)z是正態分佈的。

Python程式碼:

import numpy as np
from scipy.special import erfinv
    
def inverfsampling(mu=0, sigma=1, size=1):
    z = np.sqrt(2)*erfinv(2*np.random.uniform(size=size)-1)
    return mu+z*sigma