看spark示例代碼如何求的PI

以前也知道蒙特卡洛投針求PI,今天安裝spark,安完先要試試他自帶的幾個小程序看看能不能用,我主要會用python寫程序,也就是pyspark所以在spark裏的examples目錄深處找python的文件夾,裏面的pi.py就是。看了一下源碼是這樣的:

import sys 

from random import random 

from operator import add 

from pyspark import SparkContext 

if __name__ == "__main__": 

""" Usage: pi [partitions] """ 

sc = SparkContext(appName="PythonPi") 

partitions = int(sys.argv[1]) if len(sys.argv) > 1 else 2 

n = 100000 * partitions 

def f(_): 

x = random() * 2 - 1 

y = random() * 2 - 1 

return 1 if x ** 2 + y ** 2 < 1 else 0 

count = sc.parallelize(range(1, n + 1), partitions).map(f).reduce(add) 

print("Pi is roughly %f" % (4.0 * count / n)) sc.stop()


意思就是調用者傳個參數進去也就是投針次數,傳3他就投30萬次,然後他要造成在一個邊長爲2的正方形裏等概率投針的模擬。這裏random()產生0~1之間的數,“*2”就是0~2之間等概率的數,再“-1”x與y就變成-1到1之間等概率的數,(x,y)就是在邊長爲2的正方形裏均勻分佈的點,正方形的內切圓面積就是PI,距原點小於1的就在園內,由“PI/4 = 園內點數/總點數”可以估計PI



跑了一下效果還是不錯的,結果每次都不一樣但在3.14附近,當然他用MapReduce,我也可以寫一個不用分佈計算的嘛,然後拿C++寫了一個:

#include <iostream> #include <cmath> #include <stdlib.h> using namespace std; int main() { int n; cout<<"鍵入模擬投針次數:\n"; cin>>n; int in_circle_cnt=0; for(int i=0;i<=n;i++) { double x=(double(rand()%1000)/1000.0)*2-1; double y=(double(rand()%1000)/1000.0)*2-1; double dist=x*x+y*y; if(dist<=1.0) in_circle_cnt++; } cout<<"PI值約爲:"<<4.0*double(in_circle_cnt)/double(n)<<endl; return 0; } 

意思是到了,效果很差模擬上億次也不太好,而且相同輸入每次都一樣結果,當然了,差別就在隨機函數上了,我C++裏用的是C標準庫的僞隨機表,而python的隨機函數random()要優秀的多,才能儘量造成隨機且均勻分佈的感覺。

發佈了28 篇原創文章 · 獲贊 32 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章