CANBULA Bilim Bilişim Günlüğü

23Nis/110

Monte Carlo Yöntemi ile Pi Sayısının Hesaplanması

Bu aralar C++ ile Fortran arasında karşılaştırmalar yapıyorum. Hem bol döngülü hem de bol bol rastgele sayı üretmek gereken bir işlem olan monte carlo yöntemi ile pi sayısını hesaplayacak bir algoritma yazdım. Kodları ve sonucu da paylaşmak istedim. Önce C++ kodu ile başlayalım.

Selec All Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <complex>
#include <iomanip>
 
using namespace std;
 
int main() {
	int looplimit = 10000;
	int randomres = 1000000;
	int i;
	int j;
	double x;
	double y;
	double rin = 0.0;
	double rout = 0.0;
	double r;
	int basla;
	int bitir;
	basla = clock();
	srand(basla);
	for(i=0;i<looplimit;i++) {
		for(j=0;j<looplimit;j++) {
			x = ((rand()%randomres)*1.0)/(randomres*1.0);
			y = ((rand()%randomres)*1.0)/(randomres*1.0);
			r = sqrt(pow(x,2)+pow(y,2));
			if(r<1.0) {
				rin++;
			} else {
				rout++;
			}
		}
	}
	bitir = clock();
	cout << setw(12) << setprecision(10) << fixed << 4.0*rin/(rin+rout);
	cout << setw(22) << " ";
	cout << setw(6) << setprecision(3) << fixed << (bitir-basla)*1.0/CLOCKS_PER_SEC << "s" << endl;
	return 0;
}

Şimdi de aynı işlemi yapacak Fortran kodunu yazalım.

Selec All Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
program pihesap
        implicit none
        integer,parameter :: hassas = selected_real_kind(15,307)
        real(hassas),parameter :: res = 10000.
        real(hassas) :: x,y,r,xrast,yrast,rin,rout
        integer :: I,J,xint,yint,clockint,basla,bitir,zamanboyut
        xint = int(res)
        yint = int(res)
        call system_clock(basla,zamanboyut)
        call srand(basla)
        rin = 0.
        rout = 0.
        do I=1,xint
                do J=1,yint
                        x=rand()
                        y=rand()
                        r = sqrt(x**2. + y**2.)
                        if(r.le.1.) then
                                rin = rin + 1.
                        else
                                rout = rout + 1.
                        end if
                end do
        end do
        call system_clock(bitir)
        write(*,"(f12.10,22x,f6.3,a1)") 4.*rin/(rin+rout),(bitir-basla)*1.0/zamanboyut,"s"
end program pihesap

Son olarak da bunları derleyecek ve sonuçlarını beraber gösterecek bir bash script yazdım. İşletim sisteminiz Linux ise ve sisteminizde gcc derleyici bulunuyorsa bu script'i kullanabilirsiniz.

Selec All Code:
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
echo "__________PI_HESAPLAMA_PROGRAMI__________"
echo "PI_SAYISI________________HESAPLAMA_ZAMANI"
echo "_______________FORTRAN_95________________"
gfortran -o pihesapf95 pihesap.f95
./pihesapf95
echo "__________________C++____________________"
g++ -o pihesapcpp pihesap.cpp
./pihesapcpp
echo "========================================="

Gelelim elde ettiğim sonuçlara:

__________PI_HESAPLAMA_PROGRAMI__________
PI_SAYISI________________HESAPLAMA_ZAMANI
_______________FORTRAN_95________________
3.1414098000                       3.743s
__________________C++____________________
3.1418940400                       6.480s
=========================================

Sonuçlardan açıkça görülüyor ki her iki kodla da pi sayısı oldukça yakın olarak hesaplanıyor. Kodlardaki looplimit ve res değişkenlerinin değeri arttırılarak deneme sayısı arttırılabilir. Hesaplama zamanlarına baktığımızda da fortran'ın c++'a kıyasla neredeyse 2 kat daha hızlı olduğunu söyleyebiliriz. Bu da nümerik işlemlerde neden hala ısrarla fortran kullandığımızın bir açıklaması olsa gerek.

Bu yazıyı beğendiniz mi?

RSS Kaynağımıza abone olun!

Yorumlar (0) Geri izlemeler (0)

Yorum yapılmadı.


Leave a comment

(required)

Geri izleme yok.