40
1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo određene količine n različitig supstanci (molovi) kolicina 1, kolicina 2,..., kolicina n koje ćemo da pomešamo. Pitamo se koji su njihovi molski udeli u smeši x 1,x 2,...x n. Molski udeli predstavljaju odnose količine date supstance i ukupnog broja molova smeše tj. # n kolicina kolicina kolicina kolicina x + + + = ... 2 1 1 1 n kolicina kolicina kolicina kolicina x + + + = ... 2 1 2 2 .... n kolicina kolicina kolicina n kolicina n x + + + = ... 2 1 Radi skraćenog pisanja uvešćemo, kao u matematici, notaciju sa indeksima pa ćemo kolićine pisati kao kolicina i (i=1,..,n) a molske udele kao x i , (i=1,...,n). Tako bi u matematici skraćeno napisali da se molski udeli računaju kao ## n i kolicina kolicina x n i i i i ,..., 1 , 1 = = = Kao naš prvi pokušaj rešenja ovog problema napisaćemo program za proračun molskih udela samo za tri supstance. 1 program mudeli_proba1 2 3 real :: kolicina1,kolicina2, kolicina3 4 real :: x1,x2,x3 5 real :: smesa 6 7 !Unos kolicina supstanci 8 print*,"Supstanca 1" 9 read*,kolicina1 10 11 print*,"Supstanca 2"

Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

1

Programki jezik F II deo

Indeksirane promenljive Uzmimo jednostavan problem. Imamo određene količine n različitig supstanci (molovi) kolicina 1, kolicina 2,..., kolicina n koje ćemo da pomešamo. Pitamo se koji su njihovi molski udeli u smeši x 1,x 2,...x n. Molski udeli predstavljaju odnose količine date supstance i ukupnog broja molova smeše tj. #

nkolicinakolicinakolicina

kolicinax+++

=...21

11

nkolicinakolicinakolicina

kolicinax+++

=...21

22

....

nkolicinakolicinakolicina

nkolicinanx+++

=...21

Radi skraćenog pisanja uvešćemo, kao u matematici, notaciju sa indeksima pa ćemo kolićine pisati kao kolicinai (i=1,..,n) a molske udele kao xi, (i=1,...,n). Tako bi u matematici skraćeno napisali da se molski udeli računaju kao ##

nikolicina

kolicinax n

ii

ii ,...,1,

1

==

∑=

Kao naš prvi pokušaj rešenja ovog problema napisaćemo program za proračun molskih udela samo za tri supstance. 1 program mudeli_proba1 2 3 real :: kolicina1,kolicina2, kolicina3 4 real :: x1,x2,x3 5 real :: smesa 6 7 !Unos kolicina supstanci 8 print*,"Supstanca 1" 9 read*,kolicina1 10 11 print*,"Supstanca 2"

Page 2: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

2

12 read*,kolicina2 13 14 print*,"Supstanca 3" 15 read*,kolicina3 16 17 !Izracunavamo sumu kolicina 18 smesa = kolicina1 + kolicina2 + kolicina3 19 20 !Molski udeli 21 x1 = kolicina1/smesa 22 x2 = kolicina2/smesa 23 x3 = kolicina3/smesa 24 25 !Prikaz na ekran 26 print*,"x1=",x1 27 print*,"x2=",x2 28 print*,"x3=",x3 29 endprogram mudeli_proba1 Kada ovaj program pokrenemo i unesemo odgovarajuće podatke dobićemo sledeći rezultat na ekranu Supstanca 1 123.5 Supstanca 2 321.516 Supstanca 3 20.02 x1= 0.2655708 x2= 0.6913788 x3= 4.3050434E-02 Press any key to continue . . . Ovo bi odgovaralo matematičkom neskraćenom prikazu problema (#) i naravno, savršeno dobro radi ako imate uvek samo tri supstance koje mešate. Šta ako imate jednom 4 drugi put 5 ili ,na primer, treći put 60 supstanci. Za 4 ili pet supstanci bi se još i snašli, jer bi smo dodali odgovarajuće linije u prethodni program. Zamislite samo koliko bi bila dugačka linija 18 za malo veći broj supstanci. Do sada nismo spominjali, za naše jednostavne programe, detalje o dužini naredbe u karakterima. Evo sada tih detalja: - svaka programska linija može imati od 0 do 132 karaktera - naredba se može nastaviti karakterom & ali se naredba ne sme prekinuti usred ključne reči, imena promenljive ili konstanti - svaka naredba može imati do 40 linija. Tako bi smo mogli naredbu u liniji 18 napisati kao

Page 3: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

3

smesa = kolicina1 + & kolicina2 + & kolicina3 Ali ako imamo 60 supstanci, tu se već postavlja pitanje smisla korigovati prethodni program. Ima li bolje rešenje? (Ovo je naravno retoričko pitanje). Neko bi se setio da smo već radili kako se sumira n brojeva i da bi smo mogli koristiti do strukturu, pa bi poboljšana verzija izgledala ovako. 1 program mudeli_proba1a 2 integer,parameter :: n = 3 3 integer :: i 4 real :: kolicina 5 real :: x 6 real :: smesa 7 8 smesa = 0.0 9 10 do i=1,n 11 !Unos kolicina supstanci 12 print*,"Supstanca ", i 13 read*,kolicina 14 15 !Dodajemo kolicinu svake supstance 16 smesa = smesa + kolicina 17 enddo 18 19 do i=1,n 20 !Moramo ponovo uneti kolicinu svake supstance 21 print*,"Supstanca ", i 22 read*,kolicina 23 24 !Molski udeli 25 x = kolicina/smesa 26 print*, "molski udeo supstance ",i," je ",x 27 enddo 28 endprogram mudeli_proba1a Kada startujemo ovaj program rezultat je sledeći Supstanca 1 123.5 Supstanca 2 321.516 Supstanca 3 20.02 Supstanca 1

Page 4: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

4

123.5 molski udeo supstance 1 je 0.2655708 Supstanca 2 321.516 molski udeo supstance 2 je 0.6913788 Supstanca 3 20.02 molski udeo supstance 3 je 4.3050434E-02 Press any key to continue . . . Primetite da imamo dve do strukture. U prvoj (linije 10-17) unosimo količine i računamo njihovu sumu. U drugoj (19-27) ponovo unosimo količine i računamo molske udele. Moramo tako jer se sa svakom naredbom 13 u prvoj do strukturi prethodna vrednost promenljive kolicina briše i unosi nova. Tako da sa izlaskom iz prve do strukture u promenljivoj kolicina imamo samo poslednju vrednost tj. 20.02. Ovo je malo bolja verzija, ali ne dovoljno. Činjenica je da samo promenom vrednosti imenovane konstante n u liniji 3 možete da koristite ovaj program za proizvoljan broj supstanci. Nedostatak je što morate dva puta da unosite količine a da ne govorimo o tome da posle linije 27 ne možete da koristite ni količine a ni molske udele jer postoje samo poslednja količina i poslednji molski udeo. Kako da ih sve zapamtimo? U ovakvom slučaju se može koristiti analogija sa skraćenim prikazom uz pomoć indeksa (##). Tako dolazimo do takozvanih "indeksiranih promenljivih" koje su najkorisnije strukture podataka sa stanovišta inženjerskih proračuna. U prethodnom primeru bi se količine i udeli mogli napisati kao: kolicina(1), kolicina(2),.... i x(1), x(2),..., odnosno u opštem slučaju se ovakve indeksirane promenljive označavaju kao promenljiva(indeks) gde ovde promenljiva predstavlja uređen niz promenljivih istog tipa gde indeks određuje jedan član date indeksirane promenljive i indeks se predstavlja celobrojnim izrazom. Ovo je jednodimenziona promenljiva (ima jedan indeks) i naziva se vektor. Prethodni primer ćemo prepraviti i umesto običnih promenljivih koristiti indeksirane. 1 program mudeli_proba2 2 integer,parameter :: n = 3 3 integer :: i 4 real,dimension(n) :: kolicina 5 real,dimension(n) :: x 6 real :: smesa 7 8 smesa = 0.0 9 10 do i=1,n 11 !Unos kolicina supstanci 12 print*,"Supstanca ", i

Page 5: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

5

13 read*,kolicina(i) 14 15 !Dodajemo kolicinu svake supstance 16 smesa = smesa + kolicina(i) 17 enddo 18 19 do i=1,n 20 !Molski udeli 21 x(i) = kolicina(i)/smesa 22 print*, "molski udeo supstance ",i," je ",x(i) 23 enddo 24 endprogram mudeli_proba2 Posle startovanja ovog programa dobićemo sledeće Supstanca 1 123.5 Supstanca 2 321.516 Supstanca 3 20.02 molski udeo supstance 1 je 0.2655708 molski udeo supstance 2 je 0.6913788 molski udeo supstance 3 je 4.3050434E-02 Press any key to continue . . . Mnogo bolje! Kao prvo samo smo jednom uneli količine u prvoj do strukturi (linije 10-17) i one su zapamćene u niz, tj. vektor. U drugoj do strukturi (linije 19-23) smo izračunali novi vektor molskih udela koristeći već zapamćen vektor kolicina. Kao indeks smo koristili kontrolnu promenljivu petlje. U opštem slučaju, do petlja i indeksirane promenljive jako dobro idu zajedno jer se kontrolna promenljiva petlje koristi u izrazu za indeks indeksirane promenljive. Ostaje da prokomentarišemo da se deklaracija indeksiranih promenljivih razlikuje od običnih promenljivih. Zašto? Kao prvo, obična promenljiva ima jednu vrednost određenog tipa (npr. linije 3 ili 6) dok indeksirana promenljiva ima više vrednosti istog tipa. Pitanje je koliko? Na primer, elementi indeksirane promenljive x su x(1), x(2),..., i dokle?. Neko bi rekao- pa do n. A koliko je to n. Pa to moramo da kažemo, tj. koliki je maksimalan indeks niza. To se postiže naredbom za deklaraciju tipa uz atribut dimension tj. tip,dimension(maxindeks) :: vektor koja kaže da indeksirana promenljiva vektor ima maksimalan indeks maxindeks. Nije dozvoljen indeks veći od toga. A koliki je minimalan. Naravno 1 (u nekim programskim jezicima je 0). Pri tome je svaki element indeksirane promenljive istog tipa zadatog sa tip . Tako smo u našem programu naredbom

Page 6: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

6

real,dimension(n) :: x deklarisali indeksiranu premnljivu x čiji je maksimalan indeks n (prethodno definisana eksplicitna konstanta) i svi elementi su tipa real. Zapazite da smo mogli linije 3 i 4 zameniti jednom tj. real,dimension(n) :: kolicina, x jer i kolicina i x imaju isti tip i iste dimenzije. Pored toga primetite da je u liniji 2 definisan maksimalan indeks n = 3 što opet ukazuje da maksimalno možemo da mešamo samo tri supstance. Naravno, promenom eksplicitne konstante n ukazujemo na to koliko supstanci mešamo. Ali, program nije dovoljno uopšten u tom slučaju jer moramo da ga korigujemo za neki drugi broj supstanci. Evo rešenja u kome ne moramo da korigujemo broj supstanci koje mešamo. 1 program mudeli_proba3 2 integer,parameter :: n = 100 3 integer :: i,broj_s 4 real,dimension(n) :: kolicina,x 5 real :: smesa 6 7 print*,"Koliko supstanci imamo u smesi, broj_s=" 8 read*,broj_s 9 10 if (broj_s > n) then 11 print*,"Previse je supstanci" 12 stop 13 endif 14 15 smesa = 0.0 16 17 do i=1,broj_s 18 !Unos kolicina supstanci 19 print*,"Supstanca ", i 20 read*,kolicina(i) 21 22 !Dodajemo kolicinu svake supstance 23 smesa = smesa + kolicina(i) 24 enddo 25 26 do i=1,broj_s 27 !Molski udeli 28 x(i) = kolicina(i)/smesa 29 print*, "molski udeo supstance ",i," je ",x(i) 30 enddo 31 endprogram mudeli_proba3

Page 7: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

7

Ovaj program je dosta uopšten ali moramo da prokomentarišemo da je ograničen na maksimalno 100 supstanci (pogledajte liniju 2). Da bi smo se ipak obezbedili da korisnik ne unesi broj koji je veći od 100 koristimo if strukturu (linije 10-13). Višedimenzione indeksirane promenljive (matrice) Prethodni primeri su se bavili jednodimenzionom indeksiranom promenljivom. U F-u se mogu deklarisati i koristiti i višedimenzione indeksirane promenljive (maksimalno do 7 indeksa) od kojih su dvodimenzionalne promenljive (matrice) najkorisnije jer se tro i višedimenzione promenljive relativno manje koriste. Matrice se deklarišu naredbom tip,dimension(maxindeks1,maxindeks2) :: matrica gde je matrica dvodimenziona indeksirana promenljiva pri čemu su maxindeks1, maxindeks2 maksimalni indeksi prve i druge dimenzije respektivno (minimalni indeksi su 1). Obično za matrice kažemo da redove predstavljamo prvim a kolone drugim indeksom. PRIMER: Pretpostavimo da u nekom hemijskom procesu imamo n struja molskih protoka Fi (i = 1,..,n) koje se mešaju. Svaka struja može da ima do m supstanci molskih udela xi,j (i = 1,..,n, j = 1,..,m) gde indeks i predstavlja indeks struje a indeks j indeks supstance. Pretpostavimo da postoje merači ukupnih molskih protoka za svaku struju kao i da se procesnim hromatografom određuju molski udeli svake struje koje se mešaju, ali nije ugrađen merač ukupnog protoka rezultujuće struje i ne određuju se molski udeli supstanci u rezultujućoj struji. Naš je zadatak da to odredimo. Ukupan molski protok je

niFFn

iir ,...,1,

1==∑

=

Molski udeli supstanci u rezultujućoj struji su

mjF

xFx

r

n

ijii

jr ,...,1,1,

, =⋅

=∑=

gde u ovom izrazu suma predstavlja ukupnu količinu supstance j u svim strujama. Pretpostavimo da imate iz procesa imate sledeće vrednosti protoka struja Fi (i = 1,..,3) 1 120.3 2 100 3 140.8

Page 8: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

8

i sledeću tabelu molskih udela xi,j (i = 1,..,3, j = 1,..,4) 1 2 3 4 1 0.1 0.2 0.25 0.45 2 0.5 0.5 0 0 3 0.2 0.2 0.3 0.3 Gde su u redovima struje (3 struje) a u kolonama supstance (4 supstance). Program koji će nam odrediti ukupan protok i sastav rezultujuće struje je 1 program struje_proba1 2 integer,parameter :: n=3,m=4 !Broj struja i supstanci 3 integer :: i,j 4 real,dimension(n) :: F !Protoci struja 5 real,dimension(n,m) :: x !Udelu u strujama 6 real,dimension(m) :: xr !Udeli u rezultujucoj struji 7 real :: Fr,fsup 8 9 !Unosimo protoke struja 10 do i=1,n 11 print*,"Protok struje ",i 12 read*,F(i) 13 enddo 14 15 !Unosimo udele za svaku struju 16 do i=1,n 17 print*,"Struja ",i 18 do j=1,m 19 print*,"Udeo supstance ",j 20 read*,x(i,j) 21 enddo 22 enddo 23 24 !Ukupan molski protok rezultujuce struje 25 Fr = 0.0 26 do i=1,n 27 Fr = Fr + F(i) 28 enddo 29 print *,"Ukupan protok je Fr=",Fr 30 31 !Molski udeli supstanci u rezultujucoj struju 32 do j=1,m 33 fsup = 0.0 34 do i=1,n 35 fsup = fsup + F(i)*x(i,j) 36 enddo 37 xr(j) = fsup/Fr

Page 9: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

9

38 print *,"Molski udeo supstance ",j," = ",xr(j) 39 enddo 40 endprogram struje_proba1 Ako ovaj program startujemo i unesemo zadate podatke dobićemo sledeći rezultat Protok struje 1 120.3 Protok struje 2 100 Protok struje 3 140.8 Struja 1 Udeo supstance 1 0.1 Udeo supstance 2 0.2 Udeo supstance 3 0.25 Udeo supstance 4 0.45 Struja 2 Udeo supstance 1 0.5 Udeo supstance 2 0.5 Udeo supstance 3 0 Udeo supstance 4 0 Struja 3 Udeo supstance 1 0.2 Udeo supstance 2 0.2 Udeo supstance 3 0.3 Udeo supstance 4 0.3 Ukupan protok je Fr= 3.6110001E+02 Molski udeo supstance 1 = 0.2497646 Molski udeo supstance 2 = 0.2830795 Molski udeo supstance 3 = 0.2002631 Molski udeo supstance 4 = 0.2668928 Press any key to continue . . .

Page 10: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

10

Deluje poprilično komplikovano. Pogledajte samo kako smo sada uneli molske udele. Tu primećujete ugnježdene do strukture (linije 15-22) pri čemu se matrica unosi po redovima. Kako po redovima? Za svako i se j promeni od 1 do m. Da ne zakomplikujemo priču, bolje je da pogledate rezultate i uporedite sa programom pa ćete shvatiti, kojim se redom naredbe izvršavaju. Da ponovimo, indeksirane promenljive idu sa do strukturama pri čemu su, obično, kontrolne promenljive strukture takođe i indeksi indeksiranih promenljivih. Tu treba biti poprilično obazriv jer lako može da se pogreši. Za vežbu vam predlažem da napišete program u kome ćete uneti neku matricu i izračunati na primer: sumu svih elemenata matrice, sumu nekog reda matrice, sumu neke kolone matrice ili sumu elemenata na glavnoj dijagonali. Sve je to stvar baratanja sa do petljama i indeksima matrice. Ostaje i dalje konstatacija da ovaj program nije dovoljno uopšten (pogledajte liniju 2). O tome smo već diskutovali i pokušali smo već da više uopštimo program kada su indeksirane promenljive u pitanju (pogledajte program mudeli_proba3) Još o indeksiranim promenljivama Prethodni primeri su prilično standardni kada su u pitanju vektori i matrice. U skoro svim programskim jezicima ćete naći sličan način rada. Međutim, ima nekih stvari koje su uvedene u Fortran 90 tj. u F koje olakšavaju rad se vektorima i matricama . Deklaracija indeksiranih promenljivih Nisam izričito naglasio, ali kompletnija naredba za deklaraciju indeksiranih promenljivih je tip,dimension(min:max) :: vektor za vektor ili za matricu tip,dimension(min1:max1,min2,max2):: matrica gde se zadaje opseg indeksa od najmanjeg do najvećeg sa dva celobrojna izraza razdvojena dvotačkom. Ako se najmanji indeks ne navede (kao što je to bilo u prethodnim primerima) onda se podrazumeva da ima vrednost 1. Na primer real,dimension(3) :: x ima elemente x(1),x(2),x(3) real,dimension(0:3) :: x ima elemente x(0),x(1),x(2),x(3) real,dimension(-5,2) :: y ima elementa y(-5),y(-4),y(-3),y(-2), y(-1), y(0), y(1), y(2) real,dimension(0:2,-1,2) :: A ima elemente

Page 11: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

11

A(0,-1), A(0,0), A(0,1), A(0,2), A(1,-1), A(1,0), A(1,1), A(1,2), A(2,-1), A(2,0), A(2,1), A(2,2) Konstruktor vektora Takođe u F-u postoje mogućnosti manipulacije sa indeksiranim promenljivama kao celine. Na primer, do sada smo naredbom jednako (= ) dodeljivali vrednosti pojedinim elementima indeksiranih promenljivih. U F-u postoji tzv. konstruktor vektora gde jednom naredbom možemo dodeliti vrednosti svim elementima vektora. Pogledajte ovaj kratak program. 1 program vektor1 2 real,dimension(0:3) :: vektor 3 !Konstruktor vektora, 4 !Svakom elementu vektora dodeljujemo vrednost 5 6 vektor = (/1.5,8.0,145.2,34.901/) 7 8 !Naredba print ako je vektor 9 !izraz koji se prikazuje 10 11 print*, "vektor=",vektor 12 endprogram vektor1 Rezultat ovog programa će biti vektor= 1.5000000 8.0000000 1.4520000E+02 34.9010010 Press any key to continue . . . Konstruktor vektora je u liniji 6 - pogledajte kako se to radi. Ovom naredbom se svakom elementu vektora dodeljuje vrednost. Pored toga, ako u naredbi print imate vektor, onda će se prikazati svi elementi tog vektora. U F-u postoji samo konstruktor vektora a ako hoćemo da unesemo matricu to se mora uraditi na sledeći način 1 program matrica1 2 integer,dimension(0:5) :: vektor 3 integer,dimension(0:1,0:2) :: matrica 4 5 !Konstruktor vektora, 6 !Svakom elementu vektora dodeljujemo vrednost 7 8 vektor = (/1,2,3,4,5,6/) 9 10 !Naredba print ako je vektor

Page 12: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

12

11 !izraz koji se prikazuje 12 13 print*, "vektor=",vektor 14 15 !Za matricu nemamo konstruktor ali se moze definisati 16 !iz vektora funkcijom reshape 17 18 matrica = reshape(vektor,(/2,3/)) 19 print*,"Vrsta matrice sa indeksom 0 = ",matrica(0,:) 20 print*,"Vrsta matrice sa indeksom 1 = ",matrica(1,:) 21 endprogram matrica1 Rezultat izvršavanja ovog programa je vektor= 1 2 3 4 5 6 Vrsta matrice sa indeksom 0 = 1 3 5 Vrsta matrice sa indeksom 1 = 2 4 6 Press any key to continue . . . odnosno vrednosti elementi vektora vektor(0),vektor(1),vektor(2),vektor(3),vektor(4),vektor(5) postaju vrednosti elementa matricem, redom matrica(0,0), matrica(1,0), matrica(0,1), matrica(1,1), matrica(0,2), matrica(1,2) Primetite da se vektor u matricu "smešta" po kolonama a ne po redovima. Obratite pažnju na proceduru. Prvo je unet vektor pomoću konstruktora vektora (linija 8) a onda je od vektora formirana matrica (linija 18) sa istim brojem elemenata (u ovom slučaju 6 elemanata vektora transformisan u matricu sa 2 reda i 3 kolone). Da ste slučajno liniju 18 napisali ovako 18 matrica = reshape(vektor,(/3,2/)) prijavila bi vam se greška pri startovanju programa jer npr., nije dozvoljeno da od matrice koja je deklarisana da ima 2 reda i 3 kolone napraviti matricu sa 3 reda i 2 kolone tj. mora se poštovati deklaracija date matrice (linija 3). Podnizovi Takođe se može baratati ne samo na celokupnim vektorom nego samo na delovima nekog vektora, odnosno da se iz datog niza izvuče podniz. Za to služi tzv. triplet indeks notacija. U tom slučaju se u zagradama gde smo do sada stavljali celobrojne izraze i referencirali pojedine elemente vektora (na primer, v(3) referencira element vektora v sa indeksom 3) može napisati ovako nešto v(i1:i2:i3), znači indeks se predstavlja sada sa 3 celobrojna izraza razdvojena dvotačkom. U prevodu to znači da smo iz vektora v izabrali podvektor koji ima indekse od i1 do i2 sa korakom

Page 13: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

13

i3. Neki od celobrojnih izraza i1,12,i3 se mogu i izostaviti. Na primer, za vektor v čiji su elementi v(-2),v(-1),v(0),v(1),v(2),v(3),v(4) se može izdvojiti podniz npr. v(-1:3:2) koji će predstavljati podvektor vektora v sa elementima v(-1),v(1),v(3). Programski primer je valjda najslikovitiji (zavisi za koga). 1 program vektor2 2 integer,dimension(0:10) :: v1 3 integer,dimension (-5:3) :: v2 4 5 v1 = (/39,11,21,13, & 6 44,85,60,27, & 7 118,9,14/) 8 v2 = (/13,32,33,14,53,66,71,81,90/) 9 10 !Svi elementi vektora v1 11 print *,"v1=",v1 12 !Svi elementi vektora v2 13 print *,"v2=", v2 14 15 !Deo vektora 16 print*,"v1(1:9:2)=",v1(1:9:2) 17 !Nema prve vrednosti 18 !(podrazumeva se minimalan indeks iz deklaracije) 19 print*,"v1(:9:3)= ",v1(:9:3) 20 !Nema druge vrednosti 21 !(podrazumeva se maksimalan indeks iz deklaracije) 22 print*,"v2(-2::2)=",v2(-2::2) 23 !Nema trece vrednosti,nije potrebna druga dvotacka 24 !(podrazumeva se korak1 ) 25 print*,"v1(5:9)= ",v1(5:9) 26 !Nema nijedne vrednosti 27 !To je isto kao i ceo vektor 28 print*,"v2(:)= ", v2(:) 29 !A moze i ovako 30 print*,"v2(2:-4:-2)=",v2(2:-4:-2) 31 endprogram vektor2 Rezultat izvršavanja ovog programa je v1= 39 11 21 13 44 85 60 27 118 9 14 v2= 13 32 33 14 53 66 71 81 90 v1(1:9:2)= 11 13 85 27 9 v1(:9:3)= 39 13 60 9 v2(-2::2)= 14 66 81 v1(5:9)= 85 60 27 118 9 v2(:)= 13 32 33 14 53 66 71 81 90 v2(2:-4:-2)= 81 66 14 32 Press any key to continue . . .

Page 14: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

14

Primena operatora i funkcija na celokupne nizove Takođe postoji pogodnost i mogućnost da se već spomenuti ugrađeni operatori i funkcije primene na indeksirane promenljive. Ugrađeni operatori i procedure se mogu promeniti na čitave nizove. Pri tome nizovi moraju biti odgovarajući (isti broj dimenzija (indeksa) i isti broj elemanata svakog indeksa), pri čemu se operacije izvršavaju na svaki odgovarajući element niza. Tako na primer ...real, dimension(20) :: a, b, c !Množenje dva vaktora. a = b*c !To je isto sto i do i = 1, 20 a(i) = b(i)*c(i) end do ... !Ili na primer, !Svi vektori imaju po 4 elementa integer,dimension(4) :: a, b integer,dimension(0:3) :: c integer,dimension(6:9) :: d ... a = (/1,2,3,4/) b = (/5,6,7,8/) c = (/-1,3,-5,7/) .... a = a + b ! daje a = (/ 6, 8, 10, 12 /) d = 2 *abs(c)+1 ! daje d = (/ 3, 7, 11, 15 /) Pored toga ako je rezultat izraza skalar (jedna vrednost) a dodela se vrši nizu kao celini, onda svi elementi tog niza dobijaju tu vrednost. Na primer: 1 program sveisto 2 integer,dimension(5) :: vektor 3 integer,dimension(2,3) :: matrica 4 integer ::v,m 5 6 print*,"Kojim brojem da popunimo vektor" 7 read*,v 8 print*,"Kojim brojem da popunimo matricu" 9 read*,m 10 11 vektor = v 12 matrica = m 13

Page 15: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

15

14 print*,"Vektor=",vektor 15 print*,"Matrica=" 16 print*,matrica(1,:) 17 print*,matrica(2,:) 18 19 endprogram sveisto Po izvršavanju ovog programa dobijamo: Kojim brojem da popunimo vektor 2 Kojim brojem da popunimo matricu 5 Vektor= 2 2 2 2 2 Matrica= 5 5 5 5 5 5 Press any key to continue . . . Evo i nekih ugrađenih funkcija za nizove: maxval(niz,dim) !Maksimalan element niza maxloc(niz,dim) !Lokacija maksimalnog el.niza minval(niz,dim) !Minimalan element niza minloc(niz,dim) !Lokacija minimalnog el.niza size(niz,dim) !Broj elemenata niza sum(niz,dim) !Suma elemenata niza product(niz,dim) !Proizvod elemanata niza lbound(niz,dim) !Vrednost donjeg indeksa ubound(niz,dim) !Vrednost gornjeg indeksa transpose(matrica) !Transponovanje matrice matmul(mata,matb) !Matrično množenje Dodatni argument dim ukazuje na indeks (vektor: dim=1 , matrica: dim=1 za vrstu, dim=2 za kolonu) i on je opcionalan (nekad može i da se izostavi). Evo jednog primera gde ćemo se malo pozabaviti korišćenjem ugrađenih operacija i funkcija koje funkcionišu na običnim promenljivama kao i na vektoru kao celini. Pored toga su i prikazani primeri funkcija namenjenih za vektore. 1 program funkcije_za_nizove 2 !Primeri koristenja ugradjenih elementalnih operacija 3 !i funkcija, kao i funkcija za nizove 4 integer,dimension(0:4) :: a,b,c 5 integer :: maksimalan,suma 6 integer :: i,j,polozaj,donji,gornji 7 8 a = (/1,3,-1,8,2/) 9

Page 16: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

16

10 !Primena ugradjenih operatora i funkcija 11 b = a**2 !Primena na ceo niz 12 c = abs(a)+1 13 print *,"b=",b 14 print *,"c=",c 15 16 !Isto se moze dobiti i primenom na elemente niza 17 !(koristicemu do petlju kao sto smo ranije pomenuli) 18 do i=0,4 19 b(i) = a(i)**2 20 c(i) = abs(a(i))+1 21 print *,"b(",i,")=",b(i) 22 print *,"c(",i,")=",c(i) 23 enddo 24 25 !Neke funkcije za nizove 26 print*,"Najveci element niza b je: ",maxval(b) 27 print*,"Njegova lokacija u nizu je: ",maxloc(b) 28 print*,"Broj elemenata niza je: ",size(b) 29 print*,"Suma elemenata niza je: ",sum(b) 30 print*,"Donji i gornji indeks:",lbound(b,1),ubound(b,1) 31 32 !Neke od prethodnih funkcija cemo uraditi 33 !na klasican nacin 34 donji = lbound(b,1) !Odredjujemo donji indeks 35 gornji = ubound(b,1) !Odredjujemo gornji indeks 36 37 !Racunamo maksimalan element i njegov polozaj 38 maksimalan = b(donji) 39 j = 1 40 do i = donji+1,gornji 41 j = j + 1 42 if (maksimalan < b(i)) then 43 maksimalan = b(i) 44 polozaj = j 45 endif 46 enddo 47 print *,"Maksimalan je :",maksimalan 48 print *,"Lokacija je:",polozaj 49 50 !Racunamo sumu elemenata 51 suma = 0 52 do i = donji,gornji 53 suma = suma + b(i) 54 enddo 55 print *,"Suma je :",suma 56 endprogram funkcije_za_nizove

Page 17: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

17

Rezultat izvršavanja ovog programa je b= 1 9 1 64 4 c= 2 4 2 9 3 b( 0 )= 1 c( 0 )= 2 b( 1 )= 9 c( 1 )= 4 b( 2 )= 1 c( 2 )= 2 b( 3 )= 64 c( 3 )= 9 b( 4 )= 4 c( 4 )= 3 Najveci element niza b je: 64 Njegova lokacija u nizu je: 4 Broj elemenata niza je: 5 Suma elemenata niza je: 79 Donji i gornji indeks: 0 4 Maksimalan je : 64 Lokacija je: 4 Suma je : 79 Press any key to continue . . . Primetite u ovom programu da smo kod nekih funkcija izostavili opcionalni argument dim. Da ne ostanemo dužni matricama, pogledajte sledeći primer gde smo koristili navedene funkcije na matrici. program sa_matricom real,dimension(0:3,0:3) :: a,b !Unosimo vrstu po vrstu matrice !(primetite da koristimo konstruktor vektora) a(0,:)=(/8.0,4.0,-2.0,-6.0/) a(1,:)=(/-4.0,4.0,-1.0,5.0/) a(2,:)=(/9.0,-3.0,-9.0,0.7/) a(3,:)=(/2.0,1.0,2.0,1.0/) print*," Matrica" print*,"---------------------" print "(5f5.1)",a(0,:) print "(5f5.1)",a(1,:) print "(5f5.1)",a(2,:) print "(5f5.1)",a(3,:) print*,"---------------------" !Primenjujemo funkcije na matricu

Page 18: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

18

print "(a,f5.1)"," maxval(a)=",maxval(a) print "(a,2i3)"," maxloc(a)=",maxloc(a) print "(a,5f5.1)"," maxval(a,1)=",maxval(a,1) print "(a,5i5)"," maxloc(a,1)=",maxloc(a,1) print "(a,4f5.1)"," maxval(a,2)=",maxval(a,2) print "(a,4i5)"," maxloc(a,2)=",maxloc(a,2) print*,"size(a)=",size(a) print*,"size(a,1)=",size(a,1) print*,"size(a,2)=",size(a,2) print "(a,2i3)"," lbound(a)=",lbound(a) print*,"lbound(a,1)=",lbound(a,1) print*,"lbound(a,2=",lbound(a,2) print "(a,2i3)", " ubound(a)=",ubound(a) print*,"ubound(a,1)=",ubound(a,1) print*,"ubound(a,2)=",ubound(a,2) print "(a,f5.1)"," sum(a)=",sum(a) print "(a,5f6.1)"," sum(a,1)=",sum(a,1) print "(a,4f6.1)"," sum(a,2)=",sum(a,2) b = transpose(a) print*,"Transponovana matrica a" print*,"---------------------" print"(4f5.1)",b(0,:) print"(4f5.1)",b(1,:) print"(4f5.1)",b(2,:) print"(4f5.1)",b(3,:) print*,"---------------------" print*,"matmul(a,b(0:3,0)=" print*,matmul(a,b(0:3,0)) endprogram sa_matricom Rezultat izvršavanja ovog programa je: Matrica a --------------------- 8.0 4.0 -2.0 -6.0 -4.0 4.0 -1.0 5.0 9.0 -3.0 -9.0 0.7 2.0 1.0 2.0 1.0 --------------------- maxval(a)= 9.0 maxloc(a)= 3 1 maxval(a,1)= 9.0 4.0 2.0 5.0 maxloc(a,1)= 3 1 4 2 maxval(a,2)= 8.0 5.0 9.0 2.0 maxloc(a,2)= 1 4 1 1 size(a)= 16 size(a,1)= 4

Page 19: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

19

size(a,2)= 4 lbound(a)= 0 0 lbound(a,1)= 0 lbound(a,2= 0 ubound(a)= 3 3 ubound(a,1)= 3 ubound(a,2)= 3 sum(a)= 11.7 sum(a,1)= 15.0 6.0 -10.0 0.7 sum(a,2)= 4.0 4.0 -2.3 6.0 Transponovana matrica a --------------------- 8.0 -4.0 9.0 2.0 4.0 4.0 -3.0 1.0 -2.0 -1.0 -9.0 2.0 -6.0 5.0 0.7 1.0 --------------------- matmul(a,b(0:3,0)= 1.2000000E+02 -44.0000000 73.8000031 10.0000000 Press any key to continue . . . Ovaj program nije imao nameru da vas isprepada, nego su ovi primeri sa operatorima i funkcijama nad celokupnim nizovima imali nekoliko ciljeva. Prvo, da pogledate programe i rezultate i da pokušate da razumete dobijene rezultate. Drugo, primetite u kojim slučajevima se opcionalni parametar dim izostavio i šta dobijamo kao rezultat. Treće, rezultat poziva ovih funkcija su nekad skalari a nekad vektori (npr., pogledajte koje funkcije daju realne a koje celobrojne vektore). Četvrto, da budemo iskreni, skoro sve ove funkcije možete da izbegnete i da dobijete iste rezultate na standardan način, ali pozitivna strana korišćenja operatora i funkcija na nizovima kao celinom je da su programi kraći, efikasniji i manje podložni greškama. Sada ćemo prepraviti program struje_proba1 tako što ćemo primeniti mogućnost rada nad celokupnim nizovima kao celinom. Pri tome ćemo program učiniti malo univerzalnijim i ograničiti se na 10 struja i 20 supstanci maksimalno. 1 program struje_proba2 2 !Maksimalan broj struja nx i supstanci mx 3 integer,parameter :: nx = 10,mx = 20 4 integer :: i,j,n,m 5 real,dimension(nx) :: F !Protoci struja 6 real,dimension(nx,mx) :: x !Udelu u strujama 7 real,dimension(mx) :: xr !Udeli u rezultujucoj struji 8 real :: Fr,fsup 9 10 print*,"Broj struja max=10" 11 read*,n 12 if (n<1 .or. n>nx) stop 13 print*,"Broj komponenti max=20"

Page 20: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

20

14 read*,m 15 if (m<1 .or. m>mx) stop 16 17 !Unosimo protoke struja 18 print*,"Protoci struja" 19 read*,F(1:n) 20 21 !Unosimo udele za svaku struju 22 do i=1,n 23 print*,"Struja ",i 24 read*,x(i,1:m) 25 enddo 26 27 !Ukupan molski protok rezultujuce struje 28 Fr = sum(F(1:n)) 29 print *,"Ukupan protok je Fr=",Fr 30 31 !Molski udeli supstanci u rezultujucoj struju 32 do j=1,m 33 fsup = sum(F(1:n)*x(1:n,j)) 34 xr(j) = fsup/Fr 35 print *,"Molski udeo supstance ",j," = ",xr(j) 36 enddo 37 endprogram struje_proba2 Rezultat izvršavanja ovog programa je: Broj struja max=10 3 Broj komponenti max=20 4 Protoci struja 120.3,100,140.8 Struja 1 0.1,0.2,0.25,0.45 Struja 2 0.5,0.5,0,0 Struja 3 0.2,0.2,0.3,0.3 Ukupan protok je Fr= 3.6110001E+02 Molski udeo supstance 1 = 0.2497646 Molski udeo supstance 2 = 0.2830795 Molski udeo supstance 3 = 0.2002631 Molski udeo supstance 4 = 0.2668928 Press any key to continue . . .

Page 21: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

21

Primetite u naredbi 19 da smo uneli read*,F(1:n). Neko bi se zapitao a zašto nismo ovu naredbu uneli kao read*,F jer unosimo vektor protoka struja. Ne bi to bilo ispravno jer naredbom read*,F(1:n)se unose samo elementi vektora od F(1) do F(n) dok bi naredba read read*,F očekivala onoliko protoka struja koliko ima elemanata čitav vektor F, znači od F(1) do F(nx) kako je ovaj vektor i deklarisan. Slična je priča za naredbe 24,28 i 33. Tu se opet koriste podvektori odnosno podmatrice. where struktura Pored gore navedenog, postoji i pogodna primena tzv. where strukture na celokupnen nizove. Ova struktura je slična if strukturi ali su sada "u igri" celokupni odgovarajući nizovi (rekosmo šta znači "odgovarajući nizovi"). Evo potpune where strukture where(uslov1) blok1 elsewhere(uslov2) blok2 elsewhere(uslov3) blok3 .... elsewhere blok endwhere gde su uslov1,uslov2... logički izrazi u kojima figurišu imena odgovarajućih nizova a blok1,blok2,.. su blokovi naredbi koji se izvršavaju ako je dati uslov tačan, dok blok predstavljaju naredbe koje se izvršavaju kada nijedan od uslova nije tačan. Takođe i u blokovima figurišu imena odgovarajućih nizova. Najkraća where struktura je where(uslov) blok endwhere pro čemu ako je u bloku samo jedna naredba dozvoljeno je pisati where(uslov) naredba Brzo ćemo dati primer da se ne bi izgubili. 1 program where_if 2 integer,dimension(5)::a,b 3 integer :: i 4 5 a =(/1,-1,1,1,-1/)

Page 22: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

22

6 7 !if struktura 8 do i=1,5 9 if(a(i)==1) then 10 b(i) = 10 11 else 12 b(i) = -10 13 endif 14 enddo 15 print*,"if" 16 print*,"a=",a 17 print*,"b=",b 18 19 !where struktura 20 where (a==1) 21 b = 100 22 elsewhere 23 b = -100 24 endwhere 25 print*,"where=" 26 print*,"a=",a 27 print*,"b=",b 28 endprogram where_if Rezultat izvršavanja ovog programa je if a= 1 -1 1 1 -1 b= 10 -10 10 10 -10 where= a= 1 -1 1 1 -1 b= 100 -100 100 100 -100 Press any key to continue . . . Primetite da smo jednu te istu stvar uradili if strukturom (linije 8-17) i where strukturom (linije 20-27) tj. elementi vektora b su dobili vrednosti u zavisnosti od odgovarajućih elemenata vektora a. Dinamički nizovi Na kraju ćemo još spomenuti i dinamičke nizove. Pogledajte opet program struje_proba2 i zapazite jednu činjenicu. Mi moramo da deklarišemo nizove pre njihove upotrebe. Kada ih deklarišemo, moramo da im navedemo maksimalan broj elemenata svake dimenzije sa kojima planiramo da radimo (linije 5,6,7). Da naglasimo, ove deklaracije znače i rezervisanje (alokacija) memorije računara za nizove. Ovakav način deklarisanja se zove statička deklaracija, jer mi na osnovu deklaracije znamo koje su veličine deklarisani nizovi. Međutim, mi uglavnom koristimo manje delove nizova tj.

Page 23: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

23

njihove podnizove. Ako smo galantni i preteramo sa veličinama nizova može nastati problem, naročito kod složenijih programa sa puno nizova, jer je količina memorije ograničena. Tada moramo da vodimo računa o memoriji. Jedan od načina je korišćenje tzv. dinamičkih nizova. Kod ovakvih nizova se veličina niza određuje u toku izvršavanja programa (zato se zovu dinamički). Na primeru jedne matrice ćemo objasniti korišćenje dinamičkih nizova 1) Deklaracija za dinamički niz tip,dimension(:,:),allocatable :: matrica Primetite da atribut dimension nema naznačeno koliko ima elemanata svaki indeks (ima samo dvotačke - u ovom slučaju dve dvotačke razdvojene zarezom jer je matrica u pitanju). Zatim, dodat je atribut koji allocatable označava dinamički niz (veličina će mu se odrediti naknadno u toku izvršavanja programa. 2) Alokacija memorije read *, n,m allocate(matrica(1:n,1:m),stat = problem) !promenljiva problem postaje 0 ako je alokacija !izvršena uspešno Naredba allocate služi za alociranje memorije za dati dinamički niz. U ovom primeru smo sa tastature naredbom read uneli maksimalne vrednosti svakog indeksa i alocirali memoriju sa matrica(1:n,1:m). Ako se slučajno pojavi neki problem onda se to rešava sa stat = problem. Celobrojna promenljiva problem dobija vrednost 0 ako je alokacija uspešna a različita od 0 ako alokacija nije uspešno urađena. Tako da moramo da ispitamo promenljivu problem i po potrebi zaustavimo izvršavanje programa. 3) Dealokacija niza (kada nam niz više nije potreban) deallocate(matrica) Kada nam niz više nije potreban onda memoriju "oslobađamo" naredbom deallocate. Baratanje sa dinamičkim nizovima je relativno riskantno i treba biti obazriv. Može nam se desiti da program koji koristi dinamičke nizove prosto "zakoči" tj. odbija poslušnost što se manifestuje blokiranjem rada programa. Posle ovog pričanija evo malopređašnjeg programa prepravljenog da koristi dinamičke nizove. Korigovaćemo program struje_proba2 i koristiti sve nizove kao dinamičke. 1 program struje_proba3 2 integer :: i,j,n,m,problem 3 real,dimension(:),allocatable :: F 4 real,dimension(:,:),allocatable :: x

Page 24: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

24

5 real,dimension(:),allocatable :: xr 6 real :: Fr,fsup 7 print*,"Broj struja n=" 8 read*,n 9 print*,"Broj komponenti m=" 10 read*,m 11 12 !Alociramo dinamicke nizove 13 allocate(F(n),x(n,m),xr(m),stat=problem) 14 15 !Proveravamo da li je sve u redu 16 if (problem /=0) then 17 print*,"Alokacija nizova neuspesna" 18 stop 19 endif 20 21 !Unosimo protoke struja 22 print*,"Protoci struja" 23 read*,F 24 25 !Unosimo udele za svaku struju 26 do i=1,n 27 print*,"Struja ",i 28 read*,x(i,1:m) 29 enddo 30 31 !Ukupan molski protok rezultujuce struje 32 Fr = sum(F) 33 print *,"Ukupan protok je Fr=",Fr 34 35 !Molski udeli supstanci u rezultujucoj struju 36 do j=1,m 37 fsup = sum(F(1:n)*x(1:n,j)) 38 xr(j) = fsup/Fr 39 print *,"Molski udeo supstance ",j," = ",xr(j) 40 enddo 41 deallocate(F,x,xr) 42 endprogram struje_proba3 Rezultat izvršavanja ovog programa je isti kao i programa struje_proba2 ako smo uneli iste podatke. Čisto probe radi, uneo sam pri sledećem startovanju programa da je broj struja n = 100000 i broj komponenata 100000. Dobio sam poruku da je alokacija neuspešna i program zaustavljen, a operativni sistem se samo "bunio" jer smo hteli mnogo memorije da rezervišemo. U ovom slučaju je čak i dobro prošlo. Ako to vi pokušate da uradite na vašem računaru može vam se desiti da program "pukne" i čak računar "blokira" pa da nemate drugog izbora nego da ga resetujete.

Page 25: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

25

Na kraju samo komentar. Korišćenje statičkih nizova je sigurnije dok je korišćenje dinamičkih nizova alegantnije ali mnogo riskantnije. Dinamički nizovi su uvedeni tek u Fortran 90. Ranije verzije Fortrana su imale samo statičke nizove pa mu je zamerano da je "zastareo", da je "rasipnik memorije", da moderni jezici to imaju itd. tako da se matori Fortran ne predaje i pored ovih dinamičkih nizova uvedene su još i razne novotarije (koje ćemo mi u ovom materijalu preskočiti). PRIMER: Sada ćemo napisati program za izračunavanje srednje vrednosti nekog niza i srednjeg kvadratnog odstupanja. Ovo su dve veličine koje su, verovatno, najčešće potrebne pri obradi nekih eksperimentalnih ili drugih podataka. Srednja vrednost x niza xi (i=1,...,n) se računa kao

∑=

=n

iix

nx

1

1

Srednje kvadratno odstupanje s2 se računa kao

( )∑=

−−

=n

ii xx

ns

1

22

11

Evo i programa 1 program statistika 2 integer,parameter :: maks=50 3 real,dimension(maks) :: a 4 real ::srv,s2 5 integer :: n 6 7 do 8 print *, "Broj elemenata niza: " 9 read *,n 10 if (n<=0 .or. n>maks) then 11 print*, "veci od 0 i manji ili jednak! ",maks 12 cycle 13 else 14 exit 15 endif 16 enddo 17 18 !Unos n elemenata niza 19 print *,"Uneti ",n," elemenata niza" 20 read *,a(1:n) 21 !Racunanje sr. vrednosti i sr. kvadratnog odstupanja 22 srv = sum(a(1:n))/n 23 s2 = sum((a(1:n)- srv)**2)/(n-1.0) 24 print *,"Srednja vrednost = ",srv 25 print *,"Srednje kvadratno odstupanje = ",s2 26 endprogram statistika

Page 26: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

26

Nemam mnogo komentara o ovom programu i trebalo bi da ga razumete na osnovu prethodnih razmatranja i komentara tj. da "utvrdite gradivo". Drugačije smo izveli kontrolu unosa broja elemanata niza (promenljiva n) u linijama 7-16. Uporedite to sa programom mudeli_proba3 (linije 10-13). U čemu je razlika? Takođe pogledajte linije 22 i 23. Kako bi to bilo ako bi se sume odredile nestandardan način? Unesite ovaj program i korigujte ga (pogledati npr. program mudeli_proba2). Ako startujemo ovaj program i unesemo sledeće podatke dobićemo ovakav rezultat. Broj elemenata niza: 5 Uneti 5 elemenata niza 1.8,2,2.1,1.9,2,2 Srednja vrednost = 1.9599998 Srednje kvadratno odstupanje = 1.2999997E-02 Press any key to continue . . . Moduli - korisničke procedure Prateći ovaj tekst o F-u verovatno će neko imati sledeće komentare ili pitanja: - Ovo je relativno prosto, brzo se može naučiti i može poslužiti za jednostavnije proračune, a šta ako mi treba nešto komplikovanije? Mnogo će mi vremena trebati (pogotovo meni početniku) da program napišem i istestiram. - Moram da rešim neki model koji se sastoji od sistema nelinearnih ili diferencijalnih jednačina. Kako je to čest problem valjda je to neko već rešio (nećemo valjda svaki put krenuti od točka). Kako to da iskoristim? - Zaposlio sam se u firmi koja koristi Fortran programe. Od mene zahtevaju da te programe koristim ali da napišem dodatne "procedure" ili da korigujem postojeće. Kako se to radi? Naravno, malo ko će biti prinuđen da piše kompleksne programe. Što se Fortrana tiče, enormna količina softvera već postoji i verovatno je vaš konkretan problem već neko rešio. Pitanje je samo kako do toga doći i kako to iskoristiti. Većina problema rešenih u Fortranu su napisane u tzv. korisničkim procedurama. Fortran, kao i F, poznaje function i subroutine procedure. Mnogi Fortran kompajleri, na primer, imaju već ugrađene procedure za numeričke, statističke i druge proračune. Na razne procedure možete naići u knjigama ili kao komercijalni softver u obliku biblioteka procedura. Takođe, Internet je ogromna riznica procedura i tu možete naći mnogo komercijalnih a takođe i mnogo besplatnih procedura za rešavanje raznih problema. Ove procedure su kao "crne kutije" tj. mi njima dajemo ulazne podatke a oni nama rezultate. Za korišćenje ovih procedura morate znati nekoliko stvari: kako proceduru pozvati, kako joj obezbediti ulazne podatke, kakve rezultate ćete od procedure dobiti i to je to. Naravno, kreatori procedura će vam obično i dati detaljno uputstvo o svemu tome. Odmah ćemo dati primer u F-u. Naime čak i F ima biblioteku od nekoliko procedura iz tzv. slatec biblioteke procedura. Jedna od tih procedura je i procedura za rešavanje sistema linearnih jednačina.

Page 27: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

27

PRIMER: Rešiti sledeći sistem od 3 linearne jednačine sa 3 nepoznate x1 - 5x2 + 2x3 = -19 2x1 + 3x2 + 5x3 = -16 x1 + 3x2 -2x3 = 13 Ovaj sistem bi se u matričnom obliku mogao napiasti kao

−−

=

131619

231532251

3

2

1

xxx

odnosno A⋅x = b Gde je A - matrica koeficijenata, b - vektor rezultata, x - vektor nepoznatih Program koji će ovo da reši je: 1 program linearne_jednacine 2 use slatec_module 3 integer,parameter:: maks=10 !Maksimalan broj jednacina 4 real,dimension(maks,maks) :: A 5 real,dimension(maks)::b,x 6 7 !Matrica koeficijenata 8 A(1,1:3)=(/1.0,-5.0,2.0/) 9 A(2,1:3)=(/2.0,3.0,5.0/) 10 A(3,1:3)=(/1.0,3.0,-2.0/) 11 12 !Vektor rezultata 13 b(1:3)=(/-19.0,-16.0,13.0/) 14 15 !Poziv procedure da nam nadje vektor nepoznatih x 16 call solve_linear_equation(A(1:3,1:3),x(1:3),b(1:3)) 17 18 !Resenje 19 print*,"Resenje" 20 print*,x(1:3) 21 22 !Provera 23 print*,"Provera" 24 print*,sum(A(1,1:3)*x(1:3)) 25 print*,sum(A(2,1:3)*x(1:3)) 26 print*,sum(A(3,1:3)*x(1:3)) 27 endprogram linearne_jednacine

Page 28: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

28

Koji daje sledeći rezultat Resenje -1.0000000 2.0000000 -4.0000000 Provera -19.0000000 -16.0000000 13.0000000 Press any key to continue . . . Vidimo da smo dobili traženo rešenje tj . vektor x. Čak smo i proverili da li su rešenja dobra (ako vam je provera izazvala nedoumice pitajte nekoga, pa čak i autora ovog teksta). Šta vidimo nepoznato u programu. Linija 2 use slatec_module Linija 16 call solve_linear_equation(A(1:3,1:3),x(1:3),b(1:3)) Ukratko rečeno, linija 2 kaže da koristimo pomoću naredbe use tzv. modul slatec_module (skup procedura) od kojih jednu pozivamo u liniji 16 pomoću naredbe call i zove se solve_linear_equation. Ova procedura služi za rešavanje sistema linearnih jednačina i zahteva 3 argumenta - matricu koeficijenata, vektor nepoznatih, vektor rezultata. Otkud ja sve to znam?. Pročitao sam npr. fajl slatec.1 u folderu doc instalacije F kompajlera i tu sam našao objašnjenje koje procedure ima slatec modul i kako se koriste. Cilj ovog primera je da shvatite da kada koristite procedure koje je neko napravio, morate da se informišete kako te procedure da koristite. A da bi smo razotkrili kako to u suštini radi, objasnićemo kako se prave procedure i kako se prave moduli. Procedure F poznaje function i subroutine procedure kao i Fortran. Function procedure su slične već ugrađenim funkcijama koje smo spomenuli i pozivaju se imenom sa argumentima u zagradi i vraćaju jedan rezultat, znači mogu figurisati u izrazu. Subroutine procedure mogu vratiti više rezultata pozivaju se sa call i ne mogu figurisati u izrazu. Takođe imaju u zagradi argumente (pogledajte liniju 16 programa linearne_jednacine). function procedura Pretpostavimo da nam često treba funkcija (možda nam i ne treba, ali čisto da nešto iskoristimo za objašnjavanje)

Page 29: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

29

∑=

+=

n

i

i

inf

1

11)( za različito n, gde je n ceo broj

Sume znamo da računamo ali stalno ponavljati to za različito n je neracionalno. Zato ćemo napraviti našu, korisničku funkciju tj function proceduru. Evo kako bi ona mogla da izgleda 1 function funk(n) result(vrati) 2 integer,intent(in) :: n 3 real :: vrati 4 5 integer :: i 6 vrati = 0.0 7 do i=1,n 8 vrati = vrati + (1.0+1.0/i)**i 9 enddo 10 endfunction funk Funkcija počinje sa function i završava se sa endfunction. Sada pogledajte liniju 1. Funkcija ima ima (u ovom slučaju funk). U zagradi ima argumente - promenljive razdvojene zarezima (u ovom slučaju jedan argument n). Ovi se argumenti zovu i fiktivni. Zašto fiktivni?. Pa pogledajte dobro definiciju funkcije. Nigde nema definisano koju vrednost ima argument-promenljiva n. To ćemo tek saznati kada se ova funkcija pozove. U kojoj promenljivoj će biti rezultat ove funkcije se definiše sa result gde je u zagradi ime promenljive u kojoj se smešta rezultat (u ovom slučaju promenljiva vrati). Sledeće linije ispod moraju biti deklaracije argumenata i rezultata. Linija 2 je deklaracija argumenta funkcije. integer,intent(in) :: n Tu imamo nešto novo, tj. atribut tipa promenljive intent. Ova reč u prevodu sa engleskog znači namera. Za šta smo "nameračili" ovaj argument - promenljivu. U zagradi stoji in. To znači da je argument ulazna promenljiva. U function proceduri svi argumenti moraju da imaju atribut intent(in). Detaljnije o argumentima ćemo u razmatranju subroutine procedure. Naravno, u liniji 3 je i deklaracija promenljive u kojoj se smešta rezultat (u ovom slučaju vrati). Tu smo završili sa deklarisanjem argumanata i rezultata procedure. Ostali deo definicje funkcije (linije od 5 do 9) imaju za cilj da se u promenljivu vrati izračuna ono što smo hteli. Nadam se da vam to nije problem, osim što treba primetiti da ako vam trebaju neke nove promenljive (linija 9) sve se one takođe moraju deklarisati i nazivaju se interne promenljive procedure. U programu koji poziva ovu proceduru možemo napisati npr. ... print*,funk(10) print*,funk(100)

Page 30: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

30

... što znači da smo dva puta pozvali funkciju sa stvarnim argumentima 10 i 100. To znači da argument-promanljiva n funkcije funk (koga smo nazvali fiktivni argument) jednom dobija vrednost 10 a drugi put vrednost 100. Obratite pažnju da tip stvarnog argumenta mora odgovarati tipu fiktivnog argumenta. Posle ova dva poziva funkcijje funk dobili smo odgovarajuće rezultate na ekran, odnosno 24.3589268 2.6603598E+02 Press any key to continue . . . subroutine procedura Za razliku od function procedure, subroutine procedure mogu vratiti više od jednog rezultata. Dosta toga što smo rekli za function procedure važi i za subroutine procedure. PRIMER: Napisaćemo jednu (poprilično beskorisnu) proceduru koja zahteva dva broja i vraća vam njihove recipročne vrednosti 1 subroutine reciproc(a,b,arec,brec) 2 real,intent(in) :: a,b 3 real,intent(out) :: arec,brec 4 5 arec = 1.0/a 6 brec = 1.0/b 7 endsubroutine reciproc Procedura počinje subroutine i završava sa endsubroutine. Linija 1 definiše ime procedure (u ovom slučaju reciproc) i u zagradi fiktivne argumente (u ovom slučaju a,b,arec,brec). Linija 2 i 3 definiše za šta su ovi argumenti namenjeni pomoću intent. Argumenti a i b su ulazni (in) a arec i brec su izlazni (out). Da ponovimo, in argumenti se dobijaju od programa koji poziva ovu proceduru i zato se zovu ulazni (pogledajte da nigde nisu dobili svoje vrednosti a ipak figurišu u linij 5 i 6 tj. u izrazu, odnosnu na desnoj strani naredbe dodeljivanja). Argumenti koji su out su izlazni argumenti i oni dobijaju svoje vrednosti u proceduri kao promenljive u naredbi dodeljivanja linije 5 i 6, i vraćaju se kao rezultati programu koji ih je pozvao. Ako koristimo ovu proceduru u nekom programu možemo je pozvati naredbom call sa stvarnim argumentima npr: ... call reciproc(10.0,100.0,rez1,rez2) print*,rez1,rez2 call reciproc(2.0,20.0,rez1,rez2) print*,rez1,rez2 ...

Page 31: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

31

i dobiti sledeći rezultat na ekran 0.1000000 9.9999998E-03 0.5000000 5.0000001E-02 Press any key to continue . . . Fiktivni argumenti subroutine procedure mogu imati sledeće atribute što se ulazno-izlaznih karakteristika tiče (intent) intent(in) - ulazni argument intent(out) - izlazni argument intent(inout) - ulazno-izlazni argument Da objasnimo. Ulazni argumenti dobijaju vrednost iz programa koji tu proceduru poziva. Izlazni argumenti dobijaju vrednost u proceduri i vraćaju se kao rezultati. Ulazno-izlazni argumanti dobijaju svoje vrednosti u programu koji ih poziva, ali menjaju svoje vrednosti u proceduri. Evo jedne takve procedure koja dobija dva broja pa im zameni vrednosti (možda i nije tako beskorisna). 1 subroutine zameni(a,b) 2 real,intent(inout) :: a,b 3 4 real :: menjam 5 menjam = a 6 a = b 7 b = menjam 8 endsubroutine zameni Primetite da fiktivni argumenti a i b "već postoje" jer se nalaze sa leve strane linije 5 i 6 ali i menaju svoje vrednosti jer se nalaze sa desne strane linije 6 i 7. Deo programa koji poziva ovu proceduru bi mogao izgledati ovako .... rez1 = 1.0 rez2 = 20.0 print*,"Pre zamene = ",rez1,rez2 call zameni(rez1,rez2) print*,"Posle zamene = ",rez1,rez2 .... i dobili bi ste na ekranu sledeće vrednosti Pre zamene = 1.0000000 20.0000000 Posle zamene = 20.0000000 1.0000000 Press any key to continue . . .

Page 32: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

32

Moduli Procedure koje smo napravili se mogu "smestiti" u tzv. module. Moduli u kome se nalaze procedure (minimalno jedna procedura) koje želimo da koristimo u našem programu izgleda ovako: modul ime_modula public :: proc1,proc2,... contains function proc1(... ... endfunction proc1 subroutine proc2(... endsubroutine proc2( ... ... endmodule ime_modula Modul počine sa module a završava se sa endmodule. Sledeća linija ima deklaraciju public i iza dvotačke imena procedura razdvojene zarezom. To znači da se te procedure mogu pozvati iz drugih programa tj. one su "javno poznate". Pored public procedure se mogu deklarisate i kao private što će reći da nisu poznate van ovog konkretnog modula i koriste se "interno" u datom modulu. Same definicije procedura se nalaze iza službene reči contains (što će reći kontejner sa procedurama). Procedure iz ovog modula koje su deklarisane sa public se mogu koristiti u programu koji ima odmah posle imena programa naredbu. use ime_modula Najzad da sklopimo kockice i da napišemo program koji koristi navedene prethodne procedure smeštene u modul. 1 module moje_procedure 2 public :: funk 3 4 contains 5 function funk(n) result(vrati) 6 integer,intent(in) :: n 7 real :: vrati 8 9 integer :: i 10 vrati = 0.0 11 do i=1,n 12 vrati = vrati + (1.0+1.0/i)**i

Page 33: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

33

13 enddo 14 endfunction funk 15 16 subroutine reciproc(a,b,arec,brec) 17 real,intent(in) :: a,b 18 real,intent(out) :: arec,brec 19 20 arec = 1.0/a 21 brec = 1.0/b 22 endsubroutine reciproc 23 24 subroutine zameni(a,b) 25 real,intent(inout) :: a,b 26 27 real :: menjam 28 menjam = a 29 a = b 30 b = menjam 31 endsubroutine zameni 32 endmodule moje_procedure 33 34 program proc 35 use moje_procedure 36 integer :: n 37 real :: rez1,rez2 38 39 n = 10 40 print*,funk(n) 41 n = 100 42 print*,funk(n) 43 44 call reciproc(10.0,100.0,rez1,rez2) 45 print*,rez1,rez2 46 call reciproc(2.0,20.0,rez1,rez2) 47 print*,rez1,rez2 48 49 rez1 = 1.0 50 rez2 = 20.0 51 print*,"Pre zamene = ",rez1,rez2 52 call zameni(rez1,rez2) 53 print*,"Posle zamene = ",rez1,rez2 54 55 endprogram proc Primetite da su stvarni argumenti procedura uglavnom promenljive. U linijama 44 i 46 su prva dva argumenta eksplicitne konstante. Može, mada ovo u principu treba izbegavati. Najsigurnije je da stvarni argumenti budu takođe promenljive. Namerno sam stavio

Page 34: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

34

eksplicitne konstante kao stvarne argumente jer često studenti menjaju fiktivne argumente i imenuju ih istim imenima kao stvarne argumente. To mi ukazuje na to da sistem rada procedure nije jasan. Procedura se piše jednom a može se pozvati više puta. Da pokušamo da to malo "prizemljimo" i da vidimo kako to suštinski radi. Pogledajte liniju 44 poziva procedure reciproc i liniju 16 definicije procedure. Kada program izvršava naredbu 44 onda vrednost fiktivnog argumenta a postaje 10.0, vrednost fiktivnog argumenta b postaje 100.0 jer su to ulazni argumenti (linija 17). Onda se izvršava procedura sve do kraja (linija 22). Tu fiktivne promenljive arec i brec dobijaju svoje vrednosti (deklarisane kao out). Onda arec ima istu vrednost kao rez1 i brec ima istu vrednost kao i rez2 u liniji 44 poziva procedure. I eto ga, dobismo rez1 i rez2. Ponovnim pozivom procedure 46 se priča ponavlja ali su sada drugi stvarni argumenti. Da nastavimo. Sada se ovaj program sastoji od tzv. glavnog programa program proc i jednog modula module moje_procedure. Morate imati samo jedan glavni program a možete imati i više modula. Moduli se moraju pisati pre glavnog programa. Pri startovanju ovog programa koji ima jedan modul sa tri procedure dobijamo rezultat. 24.3589268 2.6603598E+02 0.1000000 9.9999998E-03 0.5000000 5.0000001E-02 Pre zamene = 1.0000000 20.0000000 Posle zamene = 20.0000000 1.0000000 Press any key to continue . . . Nizovi takođe mogu biti fiktivni argumenti procedura. Napisaćemo sada program koji koristi subroutine proceduru za računanje molskih udela i ukupne količinu smeše ako mešamo određene supstance zadatih količina (to smo već radili). Primer je dosta banalan i služi da uočite kako se nizovi koriste kao stvarni i kao fiktivni argumenti procedura. 1 module mesamo 2 public::mudeli_smesa 3 contains 4 subroutine mudeli_smesa(kolicina,x,smesa) 5 real,dimension(:),intent(in) :: kolicina 6 real,dimension(:),intent(out) ::x 7 real,intent(out) ::smesa 8 9 integer :: i,n 10 11 n = size(x) 12 smesa = 0.0 13 do i=1,n 14 smesa = smesa + kolicina(i) 15 enddo 16 do i=1,n

Page 35: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

35

17 x(i) = kolicina(i)/smesa 18 enddo 19 endsubroutine mudeli_smesa 20 endmodule mesamo 21 22 program mudeli 23 use mesamo 24 real,dimension(100) :: kol,udel 25 real :: pomesano 26 27 kol(1:5) = (/3.5,2.0,4.1,3.0,5.0/) 28 call mudeli_smesa(kol(1:5),udel(1:5),pomesano) 29 print*,"smesa=",pomesano 30 print*,"udeli=",udel(1:5) 31 print*,"Suma udela=",sum(udel(1:5)) 32 33 kol(1:3) = (/3.5,2.8,4.5/) 34 call mudeli_smesa(kol(1:3),udel(1:3),pomesano) 35 print*,"smesa=",pomesano 36 print*,"udeli=",udel(1:3) 37 print*,"Suma udela=",sum(udel(1:3)) 38 endprogram mudeli Rezultat izvršavanja ovog programa je smesa= 17.6000004 udeli= 0.1988636 0.1136364 0.2329545 0.1704545 0.2840909 Suma udela= 1.0000000 smesa= 10.8000002 udeli= 0.3240741 0.2592593 0.4166667 Suma udela= 1.0000000 Press any key to continue . . . Pogledajte linije 5 i 6 gde u atributu tipa promenljive stoji da je promenljiva niz (dimension atribut). Međutim u zagradi je samio dvotačka, tj. nije naznačena veličina niza. To znači da su fiktivni argumenti jednodimenzioni nizovi koji mogu biti različite veličine. Kako to? Tako što veličina niza zavisi od stvarnih argumanata pri pozivu procedure. Pogledajte linije poziva procedure (28 i 33). Pri prvom pozivu nizovi (tj podnizovi) imaju 5 elemenata a pri drugom 3 elemanta. Procedura radi korektno u oba slučaja, znači napisana je univerzalno za bilo koji broj elemanata nizova. Međutim, ako nam je unutar procedure potrebna veličina niza moramo je odrediti. Za to nam služi naredba size koju smo već spomenuli (linija 11). Imena procedura takođe mogu biti fiktivni argumenti procedura. Veoma korisno i često u upotrebi. Možda ćete vi npr. (jednog dana) morati napisati dodatne procedure za neku drugu proceduru koja se koristi u vašoj firmi. Evo primera korištenja slatec biblioteke i procedure integrate za numeričku integraciju funkcije jedne promenljive u datom intervalu. Subroutine integrate procedura kao prvi argument

Page 36: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

36

traži ime function procedure tj. funkciju koju integrali. Moramo da je definišemo u našem dodatnom modulu. 1 module funkcija 2 public :: f 3 contains 4 function f(x) result(y) 5 real,intent(in) :: x 6 real :: y 7 y = exp(2*x) 8 endfunction f 9 endmodule funkcija 10 11 program integracija 12 use funkcija 13 use slatec_module 14 15 real :: a,b,integral,tacno 16 17 a = 1.0 18 b = 5.0 19 call integrate(f,a,b,integral) 20 print*,"Integral = ",integral 21 22 !Ovaj integral moze i da se resi analiticki 23 !Odredjeni integral u intervalu a do b je 24 tacno = 1.0/2.0*(exp(2*b)-exp(2*a)) 25 print*,"Tacno = ",tacno 26 endprogram integracija Što pri startovanju daje sledeći rezultat Integral = 1.1009538E+04 Tacno = 1.1009538E+04 Press any key to continue . . . Pogledajte liniju 19. Prvi stvarni argument ima ime f ali to je ime procedure. Kako znamo? Zato što smo koristili definisani modul funkcija a u njemu je definisana function procedura sa tim imenom f. Pažljivi čitalac će primetiti da naš primer programa integracija kao i program linearne_jednacine koristi slatec_module ali ne vidimo u programu taj modul, odnosno samo postoji use slatec_module naredba koja ga poziva. Kao što sam rekao, proizvođači F-a su to uradili za nas tj. na određen način su taj modul "obradili" i smestili u tzv. biblioteke (library) a naše je da samo u našim programima pozovemo taj modul sa use i da znamo koje procedure ima i kako se te procedure

Page 37: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

37

koriste. Time se nećemo baviti jer za "pravi Fortran" postoje načini koje zavise kako od kompajlera tako i od operativnih sistema. Kako iskoristiti proceduru koju je neko drugi napisao Pretpostavimo najčešći i možda najkorisniji slučaj da ste negde na internetu "skinuli" fajl koji se zove linear_equtions.f95. Autor koji ga je napravio vam kaže da je to subroutine procedura za rešavanje sistema linearnih jednačina i dao vam je uputstvo. Uputstvo je kratko: Argumenti procedure su: a - matrica koeficijenata (ulaz) x - vektor rešenja nepoznatih (izlaz) b - vektor rezultata (ulaz) error - logička promenljiva (izlaz) F - nije došlo do greške T - došlo je do greške Deo sadržine ovog fajla je: subroutine solve_linear_equations (a, x, b, error) real, dimension (:, :), intent (in) :: a real, dimension (:), intent (out) :: x real, dimension (:), intent (in) :: b logical, intent (out) :: error .... .... .... deallocate (m, temp_row) end if end subroutine solve_linear_equations Vaše je da ovaj fajl smestite u modul i u vaš program i da ga iskoristite. Evo kako smo to uradili 1 module linearne 2 public :: solve_linear_equations 3 !Ovu proceduru je neko drugi napisao 4 !Mi smo je samo smestili u modul 5 contains 6 subroutine solve_linear_equations (a, x, b, error) 7 8 real, dimension (:, :), intent (in) :: a 9 real, dimension (:), intent (out) :: x 10 real, dimension (:), intent (in) :: b

Page 38: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

38

11 logical, intent (out) :: error 12 real, dimension (:, :), allocatable :: m 13 real, dimension (:), allocatable :: temp_row 14 integer, dimension (1) :: max_loc 15 integer :: n, k, k_swap 16 n = size (b) 17 error = size (a, dim=1) /= n .or. & 18 size (a, dim=2) /= n 19 if (error) then 20 x = 0.0 21 else 22 23 allocate (m (n, n + 1)) 24 allocate (temp_row (n + 1)) 25 m (1:n, 1:n) = a 26 m (1:n, n+1) = b 27 28 ! Triangularization phase 29 triang_loop: do k = 1, n 30 31 ! Move largest possible element to diagnoal 32 max_loc = maxloc (abs (m (k:n, k))) 33 k_swap = k - 1 + max_loc (1) 34 temp_row (k:n+1) = m (k, k:n+1) 35 m (k, k:n+1) = m (k_swap, k:n+1) 36 m (k_swap, k:n+1) = temp_row (k:n+1) 37 38 if (m (k, k) == 0) then 39 error = .true. 40 exit triang_loop 41 else 42 m (k, k:n+1) = m (k, k:n+1) / m (k, k) 43 m (k+1:n, k+1:n+1) = m (k+1:n, k+1:n+1) - & 44 spread (m (k, k+1:n+1), 1, n-k) * & 45 spread (m (k+1:n, k), 2, n-k+1) 46 end if 47 48 end do triang_loop 49 50 ! Back substitution phase 51 if (error) then 52 x = 0.0 53 else 54 do k = n, 1, -1 55 x (k) = m (k, n+1) - & 56 sum (m (k, k+1:n) * x (k+1:n))

Page 39: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

39

57 end do 58 end if 59 60 deallocate (m, temp_row) 61 62 end if 63 end subroutine solve_linear_equations 64 end module linearne 65 !************** 66 !Glavni program - mi smo ovo napisali 67 !************** 68 program linearne_jednacine 69 use linearne 70 integer,parameter::maks=10 !Maksimalan broj jednacina 71 real,dimension(maks,maks) :: A 72 real,dimension(maks)::b,x 73 logical :: greska 74 75 !Matrica koeficijenata 76 A(1,1:3)=(/1.0,-5.0,2.0/) 77 A(2,1:3)=(/2.0,3.0,5.0/) 78 A(3,1:3)=(/1.0,3.0,-2.0/) 79 80 !Vektor rezultata 81 b(1:3)=(/-19.0,-16.0,13.0/) 82 83 !Poziv procedure da nam nadje vektor nepoznatih x 84 call solve_linear_equations(A(1:3,1:3),& 85 x(1:3),b(1:3),greska) 86 87 !Resenje 88 print*,"Resenje" 89 print*,x(1:3) 90 !Da li je doslo do greske 91 print*,"Greska=",greska 92 93 !Provera 94 print*,"Provera" 95! matmul za matricno mnozenje 96 print*,matmul(A(1:3,1:3),x(1:3)) 97 endprogram linearne_jednacine

Page 40: Programki jezik F II deo - University of Novi Sadomorr/radovan_omorjan_003/F-compiler-2.pdf · 1 Programki jezik F II deo Indeksirane promenljive Uzmimo jednostavan problem. Imamo

40

Rezultat izvršavanja ovog programa je Resenje -1.0000000 2.0000000 -4.0000000 Greska= F Provera -19.0000000 -16.0000000 13.0000000 Press any key to continue . . . Već smo to jednom uradili, zar ne? Samo da, pri tome, još jednom skrenem pažnju da je ovo jedan od načina da iskoristimo već gotove procedure. Postoji još niz drugih, ali zavise od konkretnog kompajlera. Mi smo, primera radi, iskoristili način koji funkcioniše u F-u. Ovakav način takođe funkcioniše za Fortran 90/95 kompajlere. Većinu procedura koje ćete pronaći su pisane za Fortran 77 ili Fortran 90/95. Za to vam treba "pravi" Fortran 95 kompajler. Zaključak Ovaj materijal će vam najbolje koristiti ako i vi pokušate da programe koji su prezentovani kao primeri unesete u računar, pokrenete ih i igrate se s njima (proverite da li je autor možda napravio neku grešku). Programski jezik se uči pisanjem programa i otklanjanjem grešaka. Samo čitanje materijala vam neće mnogo koristiti. Umesto, ili pre nego što kažete: "Ovo sam razumeo" - upotrebljavajte više: "Ovo ću da prvo da isprobam". Kako je F namenjen učenju programiranja (odnosno Fortrana) i ako spremate ispit, onda tražite od nastavnika da vam dostavi dodatne rešene (ili nerešene) probleme da steknete utisak šta se od vas traži da bi ste ispit položili. Ako u svom budućem radu budete u situaciji da koristite "pravi" Fortran 90/95 kompajler (u trenutku pisanja ovog teksta postoji standard Fortran 2003, ali autor ovog teksta ne zna da li postoji i kompajler za Fortran 2003) onda će vam znanja o F programskom jeziku koristiti za nastavak o konkretnom Fortran sistemu.