Just My Life & My Work

C語言所產生的隨機亂數為均勻(Uniform)亂數,假如我們想要產生常態(Normal)亂數怎麼辦呢?我們先來看WiKi的Normal Distribution

normal distribution

The red line is the standard normal distribution

Gaussian function
Gaussian function: where parameter μ is the mean (location of the peak) and σ 2 is the variance (the measure of the width of the distribution). The distribution with μ = 0 and σ 2 = 1 is called the standard normal.

接著看到8 Generating values from normal distribution這個欄位:

X = sqrt( -2 ln(U) ) * cos(2 * PI * V)
Y = sqrt( -2 ln(U) ) * sin(2 * PI * V)

若想推廣到期望值和標準差可控制的狀況:

X‘ = sqrt( -2 ln(U) ) * cos(2 * PI * V) * std + mean
Y‘ = sqrt( -2 ln(U) ) * sin(2 * PI * V) * std + mean

Z是標準常態分佈~Gaussian(0, 1),而Z’是~Gaussian(mean, std^2),則Z’轉換為Z的公式為:

Z = (Z’ – mean) / std
Z’ = Z * std + mean

接下來就是程式時間囉:

/**
 Theme: Normal Distribution
 Date: 100/04/07
 compiler: Dev C++ 4.9.9.2
 Author: ShengWen
 Blog: https://cg2010studio.wordpress.com/
*/
#include <iostream>
#include <cmath>
#define NR_SAMPLES 10
using namespace std;
int main(){
	srand(time(NULL));//隨機亂數種子
	double mean = 0;//期望值
	double std = 1;//標準差
	double u, v;//uniform distribution
	double x, y;//normal distribution
	for(int i=0; i<NR_SAMPLES; i++){
	    u = rand() / (double)RAND_MAX;//RAND_MAX=32767
	    v = rand() / (double)RAND_MAX;
	    x = sqrt(-2 * log(u)) * cos(2 * M_PI * v) * std + mean;//M_PI=3.14159
	    y = sqrt(-2 * log(u)) * sin(2 * M_PI * v) * std + mean;
	    cout<<x<<endl;
	    cout<<y<<endl;
	}
	system("pause");
	return EXIT_SUCCESS;
}

輸出結果,產生[-6,6]的常態亂數

0.660637
1.4813
-1.03885
2.4052
-0.693071
-0.629039
-0.336342
0.535143
-0.473172
1.13721
-0.693372
-0.543814
-0.901281
1.99972
0.887202
-0.277707
0.463112
-0.826414
0.258715
0.424439
請按任意鍵繼續 . . .

參考:用C產生常態分佈的數值

Comments on: "[C++] 均勻亂數轉常態亂數 (Uniform to Normal)" (3)

  1. 未知 的大頭貼
  2. nai 的大頭貼

    請問如果當u=0時 這樣log(u)不就不存在了嗎? 此時亂數該如何產生

    • HappyMan 的大頭貼

      嗯……好問題,我的解決方法是限制u不要等於0,若u真的要等於0,就讓log(u)也等於0。
      但若為了科學的正確性,你可能要再查些資料。

隨意留個言吧:)~

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲