最近學習了蒙特卡洛求π的算法,本身實現了串行與並行算法。算法
(1)串行算法windows
算法思想:產生2n個隨機數據,範圍[0,1],對每一個數據點計算其座標是否知足,統計知足此關係的點的數量count,則 π=count/4n。函數
代碼:學習
#include<stdio.h> #include<math.h> #include<time.h> #include<stdlib.h> #define n 1000000000 void main() { int i,count=0; double x,y,pi; srand((int)time(NULL)); for(i=0;i<n;i++) { x=(double)(1.0*rand()/RAND_MAX); //產生0-1的隨機數 y=(double)(1.0*rand()/RAND_MAX); if(pow(x,2)+pow(y,2)<=1) { count+=1; } } pi=4.0*count/n; printf("%f",pi); }
(2)並行算法線程
算法思想:code
1. 肯定須要產生的點的個數n,參與運行的處理器數m;ip
2. 對每個處理器,生成兩個隨機數x,y,範圍[0,1];it
3. 判斷兩個隨機數x,y是否知足;io
4. 若知足,則變量COUNTi++;class
5. 重複步驟2-4,直至每一個處理器均生成n/m個隨機點;
6. 收集COUNTi的值,並累加至變量COUNT中,此即爲隨機點落在圓弧內的數量;
7. 計算π的值。
代碼:
//#include"stdafx.h" #include<windows.h> #include<stdio.h> #include<time.h> #include<math.h> #define POINT_NUM 10000000000//點的數目,儘可能不適用N、M這些會出現命名衝突 #define THREAD_NUM 10 //線程數 DWORD Thread(int *pData) { double x,y; srand(time(NULL)); for(int i=0;i<POINT_NUM/THREAD_NUM;i++) { x=(double)(1.0*rand()/RAND_MAX); //產生0-1的隨機數 y=(double)(1.0*rand()/RAND_MAX); if(pow(x,2)+pow(y,2)<=1.0) //知足範圍 (*pData)+=1; } printf("點數:%d\n",*pData); return 0; } int main(int argc,char* argv[]) { double pi; int count[THREAD_NUM]; int total=0; HANDLE h[THREAD_NUM]; printf("每一個:%d\n",POINT_NUM/THREAD_NUM); for(int i=0;i<THREAD_NUM;i++) { count[i]=0; h[i]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Thread, &count[i], 0, NULL); if(h[i]==NULL) printf("CreateThread Thread%d Error!\n",i); Sleep(1000); //若不sleep,則會出現各線程產生的點數同樣的狀況 } WaitForMultipleObjects(THREAD_NUM,h,TRUE,INFINITE); for(i=0;i<THREAD_NUM;i++) total+=(count[i]); printf("總數:%d\n",total); pi=4.0*total/POINT_NUM; printf("pi:%f\n",pi); //注意輸出格式 return 0; }
將生成點的數目寫的很是大,並在兩個程序中分別加上時間函數,輸出算法運行時間(以下的兩張圖,分別爲串行和並行算法的運行結果截圖),從中能夠看出在生成的總點數相同的前提下,兩算法的精度相差不大,但並行算法的效率更高。