Programski jezik FORmulaTRANslation je bil prvotno razvit 1950 in nato standardiziran 1977. Kasnejše posodobitve vsebujejo Fortran 90.
Glavne prednosti so:
Slabosti:
Fortran 90 je vpelljal naslednje novosti:
program hello
! Display a message to standard output
implicit none
write (unit = *, fmt= *) ”Hello World!”
end program hello
Formalno se sestoji glavni program iz
[program program-name] [specification-statements] [executable-statements] end [program [program-name]]
Kjer pomeni besedilo v oglatih oklepajih [] opcijsko uporabo. Več stavkov v eni vrstici ločimi s podpičjem;. Če pa želimo daljše stavke zlimiti v vstice dodamo na kondu znak &, ki pomeni nadaljevanje vrstice v naslednji
write (unit = *, fmt= *) &
”Nekoliko daljši pozdrav v FORTRANU.!”
implicit none ! Prisili strogo preverjanje tipov
integer :: i! 10
real :: a! 3.14159
character :: letter! a
character (len= 12) :: month ! Januar
logical :: switch! .false.
complex :: z0, z1! (1.0, 1.0)
Spremeljivke
S stavkom implicit none prisilimo strogo preverjanje tipov in ne veljajo privzeti tipi, ki so rezervirani za cela števila. Pravilo je
Implicitna raba imen spremenljivk e nevarna in se jo moramo izogibati.
Polja vsebujejo skupine vrednosti. Elementi polj so dostopna z indeksi. V Fortranu so polja shranjena v spominu kot kolone in ne kot vrstice, kot v jeziku C - column major.
Polja podajamo z atributom dimension
integer, dimension(4) :: n4
Kar rezervira 4 elemente: n4(1), n4(2), n4(3), n4(4), Prvi element je privzeto z indeksom 1. Lahko pa določimo tudi spodnje in zgornje meje:
real, dimension(-5:4) :: r
Večdimenzijska polja določimo z dodatkom dimenzij. Npr.
complex, dimension(1:10, 1:20) :: z
Dovoljeno je do 7 dimenzij:
real, dimension(2, 3, 4, 5, 6, 1) :: veliko
So deklarirana podobno kot numerični tipi. Znakovne spremenljivke lahko
Naslednja so pravilne deklaracije
character :: sex character (len= 20) :: name character (len= 10), dimension(10,10) :: carray
Za prirejanje konstantnih nizov lahko uporabimo enojne ali dvojne narekovaje.
Se imenjejo konstante in so lahko vseh tipov. Njihova vrednost se ne more spremeniti.
integer, parameter :: n = 100 real, dimension(2*n) :: r real, parameter :: pi = 3.14
Spremenljivke se kahko inicializira na poljubnem mestu v programu,
program initial_declare implicit none integer:: i = 10 real :: pi = 3.14159 character (len= 12) :: month = ”Januar” end program initial_declare
ali v glavnem programu
complex :: ci logical:: iostatus ci= (0.0, 1.0) iostatus= .true.
S tipom lahko izpeljemo lastne tipe iz obstoječih. Primer take rabe je primeren npr za spremenljivke tipa real, ki so običajno 4 byte, vendar to ni nikjer določeno. Z mehanizmom tipa pa lahko določimo izbrani tip. Npr. s specificiranjem danga decimalne vejice, kar naredimo s parametrom kind.
integer, parameter :: sp= kind(1.0) real (kind = sp), dimension(10) :: variable
Razširimo ločljivost na double
integer, parameter :: dp= kind(1.0d0) real (kind = dp) :: variable
Fortran 90 omogoča tudi izpeljane tipe s katerimi združujemo osnovne tipe. P
type person character (len=10):: name real:: age integer:: id end type person type(person) :: you, me you = person(”Janez Kranjec”, 21, 1234)
Elemente izpeljanih tipov lahko naslavljamo z znakom %. Npr za popreje deklarirani tip person
you%name! vsebuje ime you%age! starost you%id! oznaka
Pri izračunavanju izrazov z različnimi tipo spremenljivk velja pravilo, da je izračunan izraz vedno tipa, ki je višjega reda. Možno pa je tudi ročno prirejanje tipov z vgrajenimi funkcijami int(), real(), cmplx().
Fortran ima zgodovinsko gledano, množico funkcij, ki si vgrajene v sam jezik. Teh je preko 100 in operirajo s polji, biti, znaki,..., kot tudi funkcije za
V 90/95 so poleg že zastarelih opisnih relacijski operatorjev uvedeni še "normalni" izrazi za operatorje, kot jih poznamo v ostalih "modernih" jezikij. Ti so:
< ! less than <= ! less than or equal > ! greater than >= ! greater than or equal == ! equal /= ! not equal
in logični operatorji
.true. .false. .not. ! unary not .and. ! logical and .or. ! logical or .eqv. ! equivalent .neqv. ! not equivalent
if (logical-expression) then block [else if (logical-expression) then block]... [else block] end if
Primer:
if (t < 0) then ! Mraz je led = .true. else if (t > 100) then ! Toplo je para = .true. else voda = .true. mokro = .true. end if
Poleg tega so možne še druge oblike pogojnih stavkov, kot je npr elseif ali izbirni if z case. Na primer:
seasons: select case (mesec)! mesec je tipa integer case (1:2,12)! Zima, Dec, Jan, Feb write(*,*)”Zima” case(3:5)! Pomlad, Mar, Apr, May write(*,*)”Pomlad je case(6:8)! Poletje, Jun, Jul, Aug write(*,*)”Poletje” case(9:11) ! Jesen, Sep, Oct, Nov write(*,*)”Jesen” case default! če je mesec izven 1-12 write(*,*)"Vnesti je potrebno 1-12" end select seasons
do n = 1, 100 ! računaj end do
Formalno je oblika stavka zanke:
do [variable= expr1, expr2[, expr3]] blok end do
kjer je expr3 izraz za korak. Možen je tudi negativni korak:
do n = 10, 1, -1 ! računaj end do
Uporabljamo ukaz print v osnovni obliki.
print*,”Hello World”
Lahko pa uporabljamo tudi write(), ki je bolj uporaben.
result = dist(a, b, c) ... real function dist(x, y, z) real, intent(in) :: x, y, z ! zaščiteni argumenti dist = sqrt(x*x + y*y + z*z)! Priredba rezultata end function dist
call sort(nmax, a, ipass) ... subroutine sort(nmax, a, ipass) integer, intent(in):: nmax real, dimension(nmax), intent(inout) :: a integer, intent(out) :: ipass ! ... tukaj računamo ... return end subroutine sort
Podprogrami nikoli ne vračajo vrednosti. Če želimo izhod iz podprograma prej uporabimo ukaz return. Argumenti so lahko:
Neupoštevanje predpisanega obnašanja se javi pri prevajanju, kar je dobra programerska praksa.
Modul je skupek ali zbirka spremenljivk in procedur z naslednjo zgradbo:
module sort implicit none ! specifikacija spremenljivk ... contains ! specifikacija procedur subroutine sort_sub1() ... end subroutine sort_sub1 ... end modulesort
Z moduli dosežemo modularno programiranje. Module v drugih delih kode uporabimo s stavkom use:
program main use sort implicit none ... call sort_sub1() end program main
Primer uporabe modula:
program scope_main use scope_mod implicit none real :: a = 10.0, b=20.0 write(*,*)”Pred klicanjem sub1 a = ”,a,”b = ”,b call sub1(a) write(*,*)”Po klicanju sub1 a = ”,a,”b = ”,b end program scope_main
module scope_mod implicit none ! Velja za vse kar sledi contains subroutine sub1(x) real, intent(in) :: x real :: b = 5.0 b = b + 1 write(*,*)”Znotraj sub1 x = ”,x,”b = ”,b return end subroutine sub1 end module scope_mod
V primeru imamo celoten porogram iz dveh delov. Glavni (main.f90), ki uporablja sortiranje (sort.f90) sta ločeni datoteki.
f95 sort.f90 main.f90 –o progsort
Ker main uporablja sort, je pri večini prevajalnikov potrebno napisati sort.f90 pred main.f90
module another_module implicit none private ! nastavi privzeto obravnavo public :: nlimit! javno dostopna spramenljivka modula integer, parameter :: nlimit= 20! public integer :: nlocal= 0! privatna real, public :: tmp! javna spremenljivka contains ... end module another_module
Privzeta vidnost spremenljivk je public.
V naslednjem primeru
program main ... call sub1() end program main subroutine sub1() ... end subroutine sub1
sta ta dva programa povsem ločeni prevajalni enoti, ki si ne delita vidnosti. Vsa skupna informacija se prenaša z argumenti, katere se na da kontrolirati na pravilnost tipa. Tak način modularnega programiranja je bil nekoč edino možen in zazo se imanuje tudi zunanji podprogram. Primer takega programa je:
program scope_external implicit none real :: a = 10.0, b=20.0 write(*,*)”Pred klicanjem sub1 a = ”,a,”b = ”,b call sub1(a) write(*,*)”Po klicanju sub1 a = ”,a,”b = ”,b end program scope_external subroutine sub1(x) implicit none real, intent(in) :: x real :: b= 5.0 b = b + 1 write(*, *)”Znotraj sub1 x = ”,x,”b = ”,b return end subroutine sub1
V primeru je razvidno, da prevajalnik ne testira tipov. Če želimo to doseči (kar je dobra praksa), to dosežemo z ekplicitno navedbo funkcije ali podprograma.
V glavnem programu lahko pišemo tudi interne podprograme, ki jih označimo z "internal" Primer:
program main ... call sub1() contains subroutine sub1() ... end subroutine sub1 end program main
Zarani privzetega prenašanja argumentov z referenco morajo rekurzivni podprogrami
Primer rekurzivne funkcije:
res = factorial(m) ... recursive function factorial(n) result(nfact) implicit none integer, intent(in) :: n integer :: nfact if (n > 0) then nfact= n * factorial(n-1) else nfact= 1 end if end function factorial
Primer rekurzivnega podprograma:
call factorial(m,res) ... recursive subroutine factorial(n,result) integer, intent(in) :: n integer, intent(inout) :: result if (n > 0) then call factorial(n-1,result) result = result * n! Need to update result else result = 1 end if return end subroutine factorial
Fortran v vsebuje različne programske enote:
Ob pravilni rabi lahko dobimo dobro struktuirano kodo, ki je zanesljiva, razumljiva in se jo da vzdrževati.