1、用隨機投點法計算pi值
設有一半徑為r的圓及其外切四邊形。向該正方形隨機地投擲n個點。設落入圓內的點數為k。由於所投入的點在正方形上均勻分布,因而所投入的點落入圓內的概率為(PI * pow(r,2)) / (4 * pow(r,2)) = PI / 4 。所以當n足夠大時,k與n之比就逼近這一概率。從而,PI 約等於 (4*k)/n.如下圖:
實現:

#include <iostream> #include <cstdlib> #include <limits> using namespace std; // 獲得0-1之間的隨機數 double get_random_num () { return (double)rand () / RAND_MAX ; } // 用隨機投點法計算 PI double darts (int n) { int k = 0 ; for (int i = 0; i < n; ++ i) { double x = get_random_num() ; double y = get_random_num() ; if ((x * x + y * y) <= 1.0) { ++ k ; } } return (4 * k) / (double)n ; } int main() { cout << darts (200000000) << endl ; }
實現結果:
2.計算定積分
設f(x)是[0,1]上的連續函數,且0 <= f(x) <= 1。
需要計算的積分為,積分I等於圖中的面積G。
在圖所示單位正方形內均勻地作投點試驗,則隨機點落在曲線下面的概率為
假設向單位正方形內隨機地投入n個點(xi,yi)。如果有m個點落入
G內,則隨機點落入G內的概率
假定 f(x) = x * x (0 <= x <= 1)計算定積分
實現:

#include <iostream> #include <cstdlib> using namespace std; // 獲得0-1之間的隨機數 double get_random_num () { return (double)rand () / RAND_MAX ; } // 用隨機投點法計算 y = pow(x,2)定積分 double darts (int n) { int k = 0 ; for (int i = 0; i < n; ++ i) { double x = get_random_num() ; double y = get_random_num() ; if (y <= x * x) { ++ k ; } } return k / (double)n ; } int main() { cout << darts (10000000) << endl ; return 0; }
運行結果:
3.解非線性方程組
求解下面的非線性方程組
其中,x1,x2,…,xn是實變量,fi是未知量x1,x2,…,xn的非線性實函數。要求確定上述方程組在指定求根范圍內的一組解
問題分析
解決這類問題有多種數值方法,如:牛頓法、擬牛頓法、粒子群算法等。最常用的有線性化方法和求函數極小值方法。為了求解所給的非線性方程組,構造一目標函數
式中,x=(x1,x2,……xn)。易知,函數取得零點即是所求非線性方程組的一組解。
求解思路
在指定求根區域D內,選定一個隨機點x0作為隨機搜索的出發點。在算法的搜索過程中,假設第j步隨機搜索得到的隨機搜索點為xj。在第j+1步,計算出下一步的隨機搜索增量dxj。從當前點xj依dxj得到第j+1步的隨機搜索點。當x<時,取為所求非線性方程組的近似解。否則進行下一步新的隨機搜索過程。
實現:

//隨機化算法 解線性方程組 #include "stdafx.h" #include "RandomNumber.h" #include <iostream> using namespace std; bool NonLinear(double *x0,double *dx0,double *x,double a0, double epsilon,double k,int n,int Steps,int M); double f(double *x,int n); int main() { double *x0, //根初值 *x, //根 *dx0, //增量初值 a0 = 0.0001, //步長 epsilon = 0.01, //精度 k = 1.1; //步長變參 int n = 2, //方程個數 Steps = 10000, //執行次數 M = 1000; //失敗次數 x0 = new double[n+1]; dx0 = new double[n+1]; x = new double[n+1]; //根初值 x0[1] = 0.0; x0[2] = 0.0; //增量初值 dx0[1] = 0.01; dx0[2] = 0.01; cout<<"原方程組為:"<<endl; cout<<"x1-x2=1"<<endl; cout<<"x1+x2=3"<<endl; cout<<"此方程租的根為:"<<endl; bool flag = NonLinear(x0,dx0,x,a0,epsilon,k,n,Steps,M); while(!flag) { flag = NonLinear(x0,dx0,x,a0,epsilon,k,n,Steps,M); } for(int i=1; i<=n; i++) { cout<<"x"<<i<<"="<<x[i]<<" "; } cout<<endl; return 0; } //解非線性方程組的隨機化算法 bool NonLinear(double *x0,double *dx0,double *x,double a0, double epsilon,double k,int n,int Steps,int M) { static RandomNumber rnd; bool success; //搜索成功標志 double *dx,*r; dx = new double[n+1]; //步進增量向量 r = new double[n+1]; //搜索方向向量 int mm = 0; //當前搜索失敗次數 int j = 0; //迭代次數 double a = a0; //步長因子 for(int i=1; i<=n; i++) { x[i] = x0[i]; dx[i] = dx0[i]; } double fx = f(x,n); //計算目標函數值 double min = fx; //當前最優值 while(j<Steps) { //(1)計算隨機搜索步長 if(fx<min)//搜索成功 { min = fx; a *= k; success = true; } else//搜索失敗 { mm++; if(mm>M) { a /= k; } success = false; } if(min<epsilon) { break; } //(2)計算隨機搜索方向和增量 for(int i=1; i<=n; i++) { r[i] = 2.0 * rnd.fRandom()-1; } if(success) { for(int i=1; i<=n; i++) { dx[i] = a * r[i]; } } else { for(int i=1; i<=n; i++) { dx[i] = a * r[i] - dx[i]; } } //(3)計算隨機搜索點 for(int i=1; i<=n; i++) { x[i] += dx[i]; } //(4)計算目標函數值 fx = f(x,n); j++; } if(fx<=epsilon) { return true; } else { return false; } } double f(double *x,int n) { return (x[1]-x[2]-1)*(x[1]-x[2]-1) +(x[1]+x[2]-3)*(x[1]+x[2]-3); }
運行結果:
參考:王曉東《算法設計與分析》第二版
https://www.cnblogs.com/chinazhangjie/archive/2010/11/11/1874924.html