Erlang-蒙特卡洛方法求Pi
来源:互联网 发布:淘宝返现软件哪个好 编辑:程序博客网 时间:2024/05/17 02:50
这里面有两种方法,核数为2的幂见代码1,核数不为2的幂见代码2.
代码1:
-module(exe5_2).-export([start/2]).%Points 是投掷点的个数 Cores是核数,为2的幂start(Points,Cores) ->spawn(fun()->parent_proces(Points,Cores) end), io:format("").parent_proces(Points,Cores) -> PointsPerProcess = Points div Cores, creat_child_proces(Points,PointsPerProcess,Cores,Cores,[]).%创建子进程creat_child_proces(Points,PointsPerProcess,Cores,N,L) when N =:=1 -> Pid = spawn(fun()->process_points(Points,Points-PointsPerProcess*(Cores-1)) end), Father = self(), PidR = spawn(fun()->loop_control(Father,0,Cores,2) end), sendInfo(L++[Pid]++[PidR],1,Cores,2,Cores);creat_child_proces(Points,PointsPerProcess,Cores,N,L) ->Pid=spawn(fun()->process_points(Points,PointsPerProcess) end), creat_child_proces(Points,PointsPerProcess,Cores,N-1,L++[Pid]).%计算命中的点 process_points(Points,PointsPerProcess) -> apply(random, seed, tuple_to_list(now())), Count = test_points(PointsPerProcess, 0), io:format("~p 's result is ~p~n",[self(),Count]), loop_send_get(Points,Count).test_points(0, Count) -> Count;test_points(PointsPerProcess, Count) -> X = (random:uniform() * 2) - 1, Y = (random:uniform() * 2) - 1, I = X*X + Y*Y, if I < 1 -> test_points(PointsPerProcess - 1, Count + 1); true -> test_points(PointsPerProcess - 1, Count) end.%子进程部分和的发送和接收,由主进程sendInfo方法控制loop_send_get(Points,Sum) -> receive {From,Sum1,Father,PidR} -> io:format("~p from ~p to ~p result is ~p ~n",[Sum1,From,self(),Sum1+Sum]), PidR!{"ok"}, loop_send_get(Points,Sum+Sum1); {Pid,Father,PidR} -> Pid!{self(),Sum,Father,PidR}; {"getRes"} ->Res=(Sum/Points)*4, io:format("Pi:~p~n",[Res]) end.%控制每一轮迭代求和的次数,N为一轮迭代中求和的次数,初始值为0,Divisor为控制变量,初始值为2loop_control(Father,N,Cores,Divisor) ->%io:format("N:~p Divisor:~p~n",[N,Divisor]), if Cores =:= N*Divisor -> Father!{self(),"over"}, loop_control(Father,0,Cores,Divisor*2); true -> receive {"ok"} -> loop_control(Father,N+1,Cores,Divisor) end end.sendInfo(PidList,N,Cores,Divisor,Dsum) ->%io:format("Pidlist:~p ~nN:~p Cores:~p Divisor:~p Dsum:~p ~n",[PidList,N,Cores,Divisor,Dsum]), Nt = erlang:trunc(N), if Divisor =:= 2*Dsum -> Pid_1=lists:nth(1,PidList), Sum=Pid_1!{"getRes"}; Nt > Cores -> receive {From,"over"} ->sendInfo(PidList,1,Cores-Divisor/2,Divisor*2,Dsum) end; Nt rem Divisor =:= 1 -> sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum); Nt rem Divisor =/= 1 -> Pid_send = lists:nth(Nt,PidList), Pid_get = lists:nth(erlang:trunc(Nt-Divisor/2),PidList),%io:format("send:~p get:~p~n",[Pid_send,Pid_get]), Pid_send!{Pid_get,self(),lists:nth(erlang:trunc(Dsum+1),PidList)}, sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum) end.
代码2:
-module(exe5_4).-export([main/2]).%Points投掷点的总数 Core为核数,任意值main(Points,CoreNum) -> SumDie=temp(CoreNum,1), PointsPerProcess = Points div CoreNum, createP(1,CoreNum,SumDie,Points,PointsPerProcess), io:format("").temp(Num,SNum) when Num =< SNum -> SNum;temp(Num,SNum) -> temp(Num,SNum*2).createP(N,CoreNum,SumDie,Points,PointsPerProcess) when N =:= CoreNum -> register(integer_to_atom(N),spawn(fun()->process_points(Points,N,2,CoreNum,SumDie,Points,Points-PointsPerProcess*(CoreNum-1)) end));createP(N,CoreNum,SumDie,Points,PointsPerProcess) -> register(integer_to_atom(N),spawn(fun()->process_points(Points,N,2,CoreNum,SumDie,Points,PointsPerProcess) end)), createP(N+1,CoreNum,SumDie,Points,PointsPerProcess).integer_to_atom(Int) -> T=integer_to_binary(Int), binary_to_atom(T,utf8).%计算命中的点 process_points(Points,N,Die,CoreNum,SumDie,Points,PointsPerProcess) -> apply(random, seed, tuple_to_list(now())), Count = test_points(PointsPerProcess, 0), io:format("~p 's result is ~p~n",[self(),Count]), loop(Points,N,Die,SumDie,CoreNum,Count).test_points(0, Count) -> Count;test_points(PointsPerProcess, Count) -> X = (random:uniform() * 2) - 1, Y = (random:uniform() * 2) - 1, I = X*X + Y*Y, if I < 1 -> test_points(PointsPerProcess - 1, Count + 1); true -> test_points(PointsPerProcess - 1, Count) end.%每个core 收发信息loop(Points,Number,Die,SumDie,CoreNum,Count) -> if Die =:= SumDie*2 -> Res = (Count/Points)*4, io:format("Pi=~p~n",[Res]); true -> [H|L]=judge(CoreNum,Number,Die), if H =:= 1 -> [H2|_]=L, {send,To,DieThat}=H2, (integer_to_atom(To))!{Number,DieThat,Count}; true -> [H2|_]=L, {get,From,DieThat}=H2, receive {From,DieThat,Count1} -> io:format("~p ~p get info from ~p,the result is ~p~n",[Count1,Number,From,Count+Count1]), loop(Points,Number,Die*2,SumDie,CoreNum,Count1+Count) end end end.%判断每核的收发judge(SumCore,Number,Die) -> R=lslast(SumCore,Number,Die), if R =:= 1 -> if Number rem Die =:= 1 -> {DieThat,To}=find(Number,Die), [1,{send,To,DieThat}]; true -> [1,{send,Number-erlang:trunc(Die/2),Die}] end; true -> if Number rem Die =:= 1 -> [0,{get,Number+erlang:trunc(Die/2),Die}]; true -> [1,{send,Number-erlang:trunc(Die/2),Die}] end end.%判断最后一核信息发送给哪里find(Number,Die) -> Current_order=ceil(Number*2/Die), if Current_order rem 2 =:= 0 -> {Die,Number-erlang:trunc(Die/2)}; true -> find(Number,Die*2) end.%计算live的核在本轮迭代中的序号,若为最后一个标记为1.lslast(SumCores,Number,Die) -> Current_order=ceil(Number*2/Die), Sum_order=ceil(SumCores*2/Die), io:format("~p ~p ~p ~p ~p~n",[SumCores,Number,Die,Current_order,Sum_order]), if Current_order =:= Sum_order -> 1; true -> 0 end.%对小数取上界,比如ceil(15.1)=16ceil(N) -> T=trunc(N), Temp = N-T, case Temp =:= 0.000 of true -> T; false -> T+1 end.
0 0
- Erlang-蒙特卡洛方法求Pi
- erlang蒙特卡洛方法求Pi
- 求PI
- 求PI
- 蓝桥杯 求圆面积+注意求pi的方法
- 【多核程序设计】蒙特卡洛算法求pi
- 蒙特·卡罗方法求PI
- matlab数值积分方法求pi的近似值及其比较
- PHP实现简单高精度的求PI方法
- 求pi值
- 多线程求PI
- 概率算法求PI
- 求PI的值
- 近似求pi
- 近似求PI
- 近似求PI
- 求pi的值
- 求 PI(1)
- HashSet简单示例
- HDU 2574 Hdu Girls' Day
- C++文件流 掌握文本文件读写的方法
- 指数退避算法exponential back-off algorithm
- 在eclipse中快速多行注释的方法
- Erlang-蒙特卡洛方法求Pi
- CI 分页
- hdu 1907 John(anti-nim)
- 查找文件
- spring+ibatis实战
- SQLServer查看一个库里所有表的数据量
- PLSQL developer 连接不上64位Oracle 的解决方法
- 用有效的网络访问来最优化下载
- KindEditor-编辑器配置参数属性