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.
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.
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.
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.