1. 程式人生 > >0042演算法筆記——【隨機化演算法】計算π值和計算定積分

0042演算法筆記——【隨機化演算法】計算π值和計算定積分

     1、計算π值

問題描述

    設有一半徑為r的圓及其外切四邊形。向該正方形隨機地投擲n個點。設落入圓內的點數為k。由於所投入的點在正方形上均勻分佈,因而所投入的點落入圓內的概率為           。所以當n足夠大時,k與n之比就逼近這一概率。從而


    程式具體程式碼如下:

//隨機化演算法 用隨機投點法計算π值
#include "stdafx.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;

double Darts(int n);

int main()
{
	int n1 = 100,n2 = 1000,n3 = 1000,n4 = 10000,n5 = 10000000;
	cout<<"n1="<<n1<<",π1="<<Darts(n1)<<endl;
	cout<<"n2="<<n2<<",π2="<<Darts(n2)<<endl;
	cout<<"n3="<<n3<<",π3="<<Darts(n3)<<endl;
	cout<<"n4="<<n4<<",π4="<<Darts(n4)<<endl;
	cout<<"n5="<<n5<<",π5="<<Darts(n5)<<endl;
	return 0;
}

//用隨機投點法計算π值
double Darts(int n)
{
	static RandomNumber dart;
	int k = 0;

	for(int i=1; i<=n; i++)
	{
		double x = dart.fRandom();
		double y = dart.fRandom();
		if((x*x + y*y)<=1)
		{
			k++;
		}
	}

	return 4*k/double(n);
}
     程式執行結果如圖:


    2、計算定積分

    例:設f(x)=x^2,求

    解:

1)隨機投點法計算定積分

   基本思想是在矩形區域上隨機均勻的投點實現。本演算法的基本思想是在積分割槽間上隨機均勻的產生點, 即在[a,b]上隨機均勻的取點, 求出由這些點產生的函式值的算術平均值, 再乘以區間寬度, 即可解出定積分得近似解


    演算法具體程式碼如下:

//隨機化演算法 用隨機投點法計算定積分
#include "stdafx.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;

double Darts(int n,double a,double b);
double f(double x);

int main()
{
	int n1 = 100,n2 = 1000,n3 = 1000,n4 = 10000,n5 = 10000000;
	double a = 2.0,b = 3.0;
	cout<<"n1="<<n1<<",r1="<<Darts(n1,a,b)<<endl;
	cout<<"n2="<<n2<<",r2="<<Darts(n2,a,b)<<endl;
	cout<<"n3="<<n3<<",r3="<<Darts(n3,a,b)<<endl;
	cout<<"n4="<<n4<<",r4="<<Darts(n4,a,b)<<endl;
	cout<<"n5="<<n5<<",r5="<<Darts(n5,a,b)<<endl;
	return 0;
}

/*
 * 基本思想是在矩形區域內隨機均勻投點,求出由這些點
 * 產生的函式值的算術平均值,再乘以區間寬度,即可得
 * 出定積分的近似解
 */
double Darts(int n,double a,double b)
{
	static RandomNumber dart;
	double sum = 0.0;
	for(int i=0; i<n; i++)
	{
		double x = (b-a)*dart.fRandom() + a;//產生[a,b)之間的隨機數
		sum = sum + f(x);
	}
	return (b-a)*sum/n;
}

double f(double x)
{
	return x*x;
}
    程式執行結果如圖:


   
 2)概率法法計算定積分

 設f:[a,b]→[c,d]連續函式(如圖2 所示), 則由曲線y=f(x)以及x 軸和直線x=a,x=b 圍成的面積由定積分給出。根據幾何概型可知。假設向矩形區域隨機均勻的投鏢n 次, 落入陰影為K次, 又設M為x=a、x=b、y=c、y=d 所圍成的矩形面積, s 為定積分面積,則, 所以s= k/n×M。


    演算法具體程式碼 如下:

//隨機化演算法 用概率法計算定積分
#include "stdafx.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;

double Darts(int n,double a,double b,double d);
double f(double x);

int main()
{
	int n1 = 100,n2 = 1000,n3 = 1000,n4 = 10000,n5 = 10000000;
	double a = 2.0,b = 3.0;
	double d = f(b);
	cout<<"n1="<<n1<<",r1="<<Darts(n1,a,b,d)<<endl;
	cout<<"n2="<<n2<<",r2="<<Darts(n2,a,b,d)<<endl;
	cout<<"n3="<<n3<<",r3="<<Darts(n3,a,b,d)<<endl;
	cout<<"n4="<<n4<<",r4="<<Darts(n4,a,b,d)<<endl;
	cout<<"n5="<<n5<<",r5="<<Darts(n5,a,b,d)<<endl;
	return 0;
}

/*
 * f 為積分函式, n 為投鏢
 * 總數, a,b 為積分割槽間, c,d 為函
 * 數f 的值域的端點值
 */
double Darts(int n,double a,double b,double d)
{
	static RandomNumber dart;
	int k = 0;
	for(int i=0; i<n; i++)
	{
		double x = (b-a)*dart.fRandom() + a;//產生[a,b)之間的隨機數
		double y = d * dart.fRandom();

		if(y<=f(x))
		{
			k++;
		}
	}
	return d*(b-a)*k/n;
}

double f(double x)
{
	return x*x;
}
    程式執行結果如圖: