Temel Yönleriyle Fortran 90 / 95 / 2003

  Temel Konular
* Önsöz

* Fortran'a Giriş
* Fortran'nın Temelleri
* Basit ve Formatlı Okuma/Yazma
* Temel Kütüphane Fonksiyonları
* Karşılaştırma Deyimleri
* Döngüler
* Alt Programlar I
* Alt Programlar II
* Diziler
* Dinamik Diziler
* Gösterici (Pointer) Kavramı
* Katarlar (Stringler)
* Yapısal Veri Tipleri
* Dosya Yönetimi
* Modül Kavramı
* Sayısal Tipler (KINDs)
* Bit Düzeyinde Çalışmak
* Kütüphane Fonksiyonları Listesi

* Yararlanılan Kaynaklar

  İleri Uygulamalar
* - - -
* Karmaşık Sayılar
* Tarih-Saat Fonksiyonları
* Rastgele Sayılar
* Katar - Sayı Dönüşümleri
* Komut Satırı İşlemleri
* Co-Array Fortran
* Derleme Seçenekleri
* Fortran ve C

  Seçilmiş Örnekler
* Sayılar Kuramı
* Analiz
* Lineer Cebir

  Fortran 90/95 Derleyicileri
* Salford (silversoft FTN95)
* G95
* GFORTRAN

  Dış Bağlantılar
* programlama.com
* Fortran (wikipedia)

* fortran.gantep.edu.tr
* g95.org
* Hot scripts

  İletişim
* E-posta

 

Bölüm 7: Alt Programlar I

###################- (%95)


Giriş

Programla dillerinde alt program, belirli sayıda verileri kullanarak bunları işleyen ve bir sonuç üreten komut grubudur. Fortran programlama dili'de alt programların birleştirilmesi kavramına dayanır. Bu özellik bütün Yapısal Diller'in (C, Fortran, Pascal, ...) temelini oluşturur. Yapısal Diller'e hakim olmak için alt program oluşturmayı ve kullanmayı iyi öğrenmek gerekir.

Fortran'da alt programlar FUNCTION ve SUBROUTINE deyimleri ile oluşturulur. Bu bölümde, Fortran 90+ Programlama Dili'ndeki bu deyimlerle oluşturalan alt programlar, sonraki bölümde (Bölüm 8) esnek argümanlı ve anahtar argumanlı alt programlar irdelenecektir.


7.1   FUNCTION Deyimi

Function bir fonksiyon oluşturma deyimidir. Her fonksiyonun bir adı ve fonksiyona gelen değerleri gösteren argumanları (bağımsız değişkenleri) vardır. Genel olarak bir fonksiyon Şekil 7.1'deki gibi bir kutu ile temsil edilebilir:


Şekil 7.1: Bir fonksiyonun kutu gösterimi

Fonksiyonların girdilerine parametreler yada argumanlar denir. Bir fonksiyon bu parametreleri alıp bir işleme tabi tutar ve bir değer hesaplar. Bu değer, çıktı veya geri dönüş değeri (return value) olarak adlandırılır. Unutmayın ki, bir fonksiyonun kaç girişi olursa olsun sadece bir çıkışı vardır.

Fortran, kullanıcısına bu türden fonksiyon yazmasına izin verir. Genel bildirim şöyledir:


      
      tip FUNCTION isim(arguman listesi)
      ...
      isim = bir ifade
      ...
      END FUNCTION isim
burada
  • tip, fonksiyonun üreteceği değerin veri tipi (INTEGER, REAL gibi)
  • isim, Fonksiyonunun adınu tutar ve geçerli bir tanımlayıcı (valid identifier) olmalıdır.
  • arguman listesi, birbirinden virgül ile ayrılmış fonksiyon argumanları.
  • isim = bir ifade, kullanılması zorunludur ve fonksiyonun döndüreceği değer burada belirlenir.
  • END FUNCTION deyimi fonksiyon bloğunun sonunu işaret eder. Bundan sonra yazılan isim'in kullanımı isteğe bağlıdır (kullanılması zorunlu değildir).
Örneğin iki tamsayının toplamını hesaplayacak bir fonksiyon şöyle tanımlanabilir:
      INTEGER FUNCTION Topla(A, B)
      INTEGER, INTENT(IN) :: A,B
         Topla = A + B
      END FUNCTION Topla
veya
      FUNCTION Topla(A, B)
      INTEGER, INTENT(IN) :: A,B
      INTEGER :: Topla
         Topla = A + B
      END FUNCTION Topla
veya
      INTEGER FUNCTION Topla(A, B)
      INTEGER :: A, B
         Topla = A + B
      END FUNCTION Topla
INTENT(IN) özniteliği (attribute), Topla fonksiyonunun giriş argümanları (A ve B) fonksiyon içinde olası bir değişime maruz kalmasını engellemek için konmuştur. INTENT(IN), kullanımı uzman Fortran programcıları tarafından şiddetle tavsiye olunur.

Bir fonksiyon, bildirilirken ve ana programdan çağrılırken iki yöntem izlenir.

  1. İç (internal) fonksiyon bildirimi
  2. Dış (external) fonksiyon bildirimi

İç Fonksiyon Bildirimi

Fonksiyon bloğu ana programda, CONTAINS ve END PROGRAM deyimleri arasına yerleştirilir. Bu durumda, Topla fonksiyonu aşağıdaki gibi çağrılır.

Program 7.1: İç fonksiyon tanımlaması
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
PROGRAM Toplama
!--------------------------------------------------------
! 07prg01.f95
! İki sayının toplamını Topla fonksiyonu ile hesaplar.
!--------------------------------------------------------
IMPLICIT NONE
INTEGER :: X, Y, Z

   PRINT *,"Iki sayı girin:"
   READ *, X, Y

   Z = Topla(X,Y)

   PRINT *,"Toplam = ", Z 


CONTAINS

   INTEGER FUNCTION Topla(A, B)
   INTEGER, INTENT(IN) :: A,B
         Topla = A + B
   END FUNCTION Topla

END PROGRAM 

ÇIKTI

 Iki sayı girin:
2 8
 Toplam =  10

Programda, klavyeden okunan X ve Y değişkenleri fonksiyonuna parametre olarak aktarılmıştır. Bu değişkenlerin isimleri ile Topla fonksiyonunda kullanılan değişkenlerin (A ve B) isimleri aynı olması zorunlu değildir. Burara X ve Y değişkenlerinin içerikleri (yani tutukları sayısal değerler) sırasıyla A ve B değişkenlerine kopyalanmıştır. 12. satırda Z adlı tamsayı değişkenine Topla fonksiyonunun dönüş değeri (A + B değeri) atanmıştır.

Aşağıdaki programda, Faktor fonksiyonu ile 0'dan 10'a kadar olan sayılar ve faktoriyellerinin ekrana yazdırılması gösterilmiştir.

Program 7.2: Faktoriyel hesabı
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
PROGRAM Faktoriyel
!--------------------------------------------------------
! 07prg02.f95
! Faktor() fonksiyonu ile 0'dan 10'a kadar olan sayıları
! ve faktoriyellerini ekrana basar.
!--------------------------------------------------------
IMPLICIT NONE
INTEGER :: I

   DO I = 0, 10 
    PRINT *, I,"! = ", Faktor(I)
   END DO

CONTAINS

   INTEGER FUNCTION Faktor(N)
   INTEGER, INTENT(IN) :: N
   INTEGER :: J

     Faktor = 1
     DO J=1,N
       Faktor = Faktor * J
     END DO

   END FUNCTION Faktor

END PROGRAM 

ÇIKTI

 0 ! =  1
 1 ! =  1
 2 ! =  2
 3 ! =  6
 4 ! =  24
 5 ! =  120
 6 ! =  720
 7 ! =  5040
 8 ! =  40320
 9 ! =  362880
 10 ! =  3628800


Dış Fonksiyon Bildirimi

Fonksiyon bloğu ana programın dışında bildirilmek mümkündür. Bunun için önce INTERFACE bloğu oluşturulup fonksiyon örneği (prototype) ana programda bildirilmelidir. Dış bildirim kullanılarak, Topla fonksiyonu aşağıdaki gibi çağrılır.

Program 7.3: Dış fonksiyon tanımlaması
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
PROGRAM Toplama
!--------------------------------------------------------
! 07prg03.f95
! İki sayının toplamını Topla fonksiyonu ile hesaplar.
!--------------------------------------------------------
IMPLICIT NONE

! fonksiyon prototipi
INTERFACE Topla_Ornegi
  INTEGER FUNCTION Topla(A, B)
    INTEGER, INTENT(IN) :: A,B
  END FUNCTION Topla
END INTERFACE Topla_Ornegi


INTEGER :: X, Y, Z

   PRINT *,"Iki sayı girin:"
   READ *, X, Y

   Z = Topla(X,Y)

   PRINT *,"Toplam = ", Z 

END PROGRAM Toplama


! Fonksiyon bildirimi
INTEGER FUNCTION Topla(A, B)
INTEGER, INTENT(IN) :: A,B
  Topla = A + B
END FUNCTION Topla  

ÇIKTI

 Iki sayı girin:
2 8
 Toplam =  10


7.2   SUBROUTINE Deyimi

Fonksiyonlar gelen argümanlara göre sadece bir değer dödürebilir. Bir alt programla birden çok değer döndürülmek istendiğinde SUBROUTINE deyimi kullanılır. Kutu gösterimi şekil 7.2'de verilen bu türden alt programalar CALL deyimi kullanılarak çağılır.


Şekil 7.2: SUBROUTINE tipi bir alt programın kutu gösterimi

SUBROUTINE oluşturmanın genel yazım biçimi şöyledir:


     SUBROUTINE isim(argüman listesi)
     .
     .
     .
     END SUBROUTINE isim
FUNCTION ile karşılaştırıldığında, SUBROUTINE tipi alt programın bir tipi olmadığına ve ismin herhangi bir ifadeye eşitlenmediğine dikkat ediniz.

Bu kurala göre kartezyen koordinatlarda verilen bir (x, y) noktasının, kutupsal (polar) koordinattaki karşılığını (r, θ) döndüren bir bir SUBROUTINE şöyle tanımlanabilir:

     SUBROUTINE KartezyenPolar(X, Y, R, Teta)
     REAL, INTENT(IN) :: X, Y
     REAL, INTENT(OUT) :: R, Teta

       R = SQRT(x**2+Y**2)
       Teta = ATAN(Y/X)

     END SUBROUTINE KartezyenPolar
Burada X ve Y SUBROUTINE'nin giriş, R ve Teta hesaplanan çıkış argümanlarıdır. Bu subroutine aşağıdaki gibi çağrıldığında
     CALL KartezyenPolar(3.0, 4.0, mesafe, aci)
     PRINT *,mesafe, aci
(3,4) noktasının polar karşılığı (mesafe = 5.0 aci = 0.927295 değerleri) ekrana basılır.

SUBROUTINE'ler de fonksiyonlar gibi iç ve dış bildirim ile tanımlanabilir. İki bildirimin kullanılması aşağıdaki programlarda verilmiştir.

Program 7.4: İç SUBROUTINE bildirimi
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
PROGRAM Cevrim
!--------------------------------------------------------
! 07prg04.f95
! Kartezyen-polar çevrimi (iç Subroutine ile)
!--------------------------------------------------------
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.141593
REAL :: X, Y, R, T

   PRINT *,"Bir (x, y) koordinatı girin:"
   READ *, X, Y

   CALL KartezyenPolar(X, Y, R, T)

   T = T * 180.0/PI ! radyanı dereceye çevir

   PRINT *,"(x,y) -> (r,teta) karşılığı = ", R, T

CONTAINS

    SUBROUTINE KartezyenPolar(X, Y, R, Teta)
    REAL, INTENT(IN) :: X, Y
    REAL, INTENT(OUT) :: R, Teta

      R = SQRT(x**2+Y**2)
      Teta = ATAN(Y/X)

    END SUBROUTINE KartezyenPolar

END PROGRAM Cevrim 

ÇIKTI

 Bir (x, y) koordinatı girin:
3 4
 (x,y) -> (r,teta) karşılığı =  5. 53.130093


Program 7.5: Dış SUBROUTINE bildirimi
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
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: 
PROGRAM Cevrim
!--------------------------------------------------------
! 07prg04.f95
! Kartezyen-polar çevrimi (iç Subroutine ile)
!--------------------------------------------------------
IMPLICIT NONE

! Prototip
INTERFACE KarPol
   SUBROUTINE KartezyenPolar(X, Y, R, Teta)
    REAL, INTENT(IN) :: X, Y
    REAL, INTENT(OUT) :: R, Teta
   END SUBROUTINE KartezyenPolar
END INTERFACE KarPol


REAL, PARAMETER :: PI = 3.141593
REAL :: X, Y, R, T

   PRINT *,"Bir (x, y) koordinatı girin:"
   READ *, X, Y

   CALL KartezyenPolar(X, Y, R, T)

   T = T * 180.0/PI ! radyanı dereceye çevir

   PRINT *,"(x,y) -> (r,teta) karşılığı = ", R, T

END PROGRAM Cevrim 


! Bildirim
SUBROUTINE KartezyenPolar(X, Y, R, Teta)
REAL, INTENT(IN) :: X, Y
REAL, INTENT(OUT) :: R, Teta

  R = SQRT(x**2+Y**2)
  Teta = ATAN(Y/X)

END SUBROUTINE 

ÇIKTI

 Bir (x, y) koordinatı girin:
3 4
 (x,y) -> (r,teta) karşılığı =  5. 53.130093


7.3 RETURN Deyimi

Bir fonksiyon ile üretilen değer yada bir suburoutine ile üretilen değer(ler) END FUNCTION veya END SUBROUTINE deyimi ile karşılaşılınca döndürülür. Ancak, bir fonksiyon (yada subroutine) bu deyimlere ulaşılmadan her hangi bir noktadan da RETURN deyimi ile sonlandırılabilir.

Örneğin, aşağıdaki fonksiyon giriş argümanı (tamsayı N) [2, 12] aralığının dışında ise 1, aksi halde N! değerini döndürür.
     INTEGER FUNCTION Faktor(N)
     INTEGER, INTENT(IN) :: N
     INTEGER :: I

      Faktor = 1

      IF(N<1 .OR. N>12) RETURN

      DO I = 2, N
        Faktor = Faktor * I
      END DO

     END FUNCTION Faktor

7.4   Yapısal Programlama

Program içinde birden çok fonksiyon tanımlayıp kullanmak mümkündür. Fortran Programlama Dili fonksiyonların inşası dayalı bir dildir. Bu özellik bütün Yapısal Programlama Dilleri'nin (Structred Programming) temelini oluşturur. Birden çok fonksiyonun ana program tarafından nasıl çağrıldığını temsil eden blok diyagram Şekil 7.3'de gösterilmiştir.


Şekil 7.3: Ana programdan bir çok alt programın çağırılması.

Fonksiyonların sadece ana program tarafından çağrılması zorunlu değildir. Bir fonksiyon başka bir fonksiyon tarafından da çağrılabilir. Buna dair bir örnek aşağıda verilmiştir. <>Yilin_Gunu fonksiyonu, verilen bir tarihin yılın kaçıncı günü olduğunu hesaplar ve çağrıldığı yere gönderir. İnceleyiniz.

Program 7.6: Bir fonksiyonun başka bir fonksiyon tarafından çağrılması
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
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: 
42: 
43: 
44: 
45: 
46: 
PROGRAM Tarih
!--------------------------------------------------------
! 07prg06.f95
! Verilen bir tarihin yılın kaçıncı günü olduğunu
! hesaplar.
!--------------------------------------------------------
IMPLICIT NONE

  INTEGER :: gun = 1     ! tarih: 01 Ağustos 2003
  INTEGER :: ay  = 8
  INTEGER :: yil = 2003

  PRINT *, gun, ay, yil, " tarihi yılın"
  PRINT *, Yilin_Gunu(gun,ay,yil), ". günüdür"

CONTAINS

  ! yil artıl yıl ise 1 aksi halde 0 gönderir
  INTEGER FUNCTION Artik(Yil)
  INTEGER, INTENT(IN) :: Yil

      Artik = 0

      IF( mod(yil,4)  ==0 .AND. &
          mod(yil,100)/=0 .OR.  &
          mod(yil,400)==0 ) Artik = 1

  END FUNCTION Artik


  ! Yılın kaçıncı günü olduğunu hesaplar ve o günü gönderirir
  INTEGER FUNCTION Yilin_Gunu(Gun, Ay, Yil)
  INTEGER, INTENT(IN) :: Gun, Ay, Yil
  INTEGER :: I
  INTEGER :: agun(12) = (/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)

    Yilin_Gunu = gun

    DO I = 1, Ay-1
      Yilin_Gunu = Yilin_Gunu + agun(I)
      if(I==2) Yilin_Gunu = Yilin_Gunu + Artik(yil)
    END DO

  END FUNCTION

END PROGRAM Tarih 

ÇIKTI

 1 8 2003  tarihi yılın
 213 . günüdür


7.5   Örnekler

ÖRNEK 1: BINOM AÇILIMI

(a+b)n ifadesinin, binom açılım katsayıları aşağıdaki formüllle verilir:
Bunlar aslında Pascal Üçgeninin elemanları oluşturur.
   n = 1              1
   n = 2          1   2   1
   n = 3        1   3   3   1
   n = 4      1   4   6   4   1
   n = 5    1   5   10  10  5   1
   .        .
   .        .
   .        .
Açılım katsayılarını bulmak için, iki fonksiyon tanımlıyacağız: Faktor(n) ve C(n, k). Aşağıdaki program, bir döngü içerisinde, n = 1, 2, 3, 4, 5 ve 6 için binom katsayılarını ekrana basar.

Program 7.7: Binom açılımı
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
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: 
PROGRAM Binom_Acilimi
!--------------------------------------------------------
! 07prg04.f95
! Kartezyen-polar çevrimi (iç Subroutine ile)
!--------------------------------------------------------
IMPLICIT NONE
INTEGER :: n, k

  DO n = 0, 6
  DO k = 0, n
    WRITE(*,FMT='(I3)',ADVANCE='No') C(n,k)
  END DO
  WRITE(*,*)
  END DO

CONTAINS

   ! N! değerini döndürür
   INTEGER FUNCTION Faktor(N)
   INTEGER, INTENT(IN) :: N
   INTEGER :: J
     Faktor = 1
     DO J=1,N
       Faktor = Faktor * J
     END DO
   END FUNCTION Faktor

   ! C(n,k) kombinasyonunu hesaplar
   INTEGER FUNCTION C(N, K)
   INTEGER, INTENT(IN) :: N, K
     C = faktor(n)/(faktor(k)*faktor(n-k))
   END FUNCTION

END PROGRAM Binom_Acilimi 

ÇIKTI

  1
  1  1
  1  2  1
  1  3  3  1
  1  4  6  4  1
  1  5 10 10  5  1
  1  6 15 20 15  6  1

ÖRNEK 2: XXX

ÖRNEK 3: XXX



Powered by PHP