Diapositiva 1 - Docenti.unina

annuncio pubblicitario
Programmazione Strutturata:
Procedure, Subroutines, Functions
Programmazione Strutturata: motivazione
Dato un problema è possibile suddividerlo in sottoproblemi
più facili da capire e da risolvere, in modo che scelto un
algoritmo che risolva ciascun sottoproblema, l’algoritmo che
risolve il problema di partenza può essere ottenuto dalla
composizione degli algoritmi più semplici.
In altre parole, l’algoritmo risolutivo di un problema
complesso può essere descritto per mezzo di macroblocchi
che rappresentano algoritmi risolutivi di problemi più
semplici.
2
Programmazione Strutturata: tecnica
Un macroblocco può essere codificato come un’unità di
programma indipendente o procedura.
Le procedure sono moduli di programma che concorrono a
costituire programmi complessi atti a risolvere problemi
complessi.
3
Principali vantaggi della programmazione strutturata :
 Sviluppo e debugging indipendente delle singole procedure:
ogni macroblocco può essere codificato e compilato come un’unità di
programma indipendente (procedura);
 Codice riutilizzabile:
è possibile che una procedura sia utilizzabile in più programmi oppure
più volte nello stesso programma, con una conseguente riduzione del
lavoro complessivo di programmazione ed una semplificazione della
fase di correzione degli errori.
 Isolamento degli effetti collaterali:
le procedure comunicano con il programma principale, che le invoca,
solo attraverso una lista di variabili. Le uniche variabili del programma
principale che possono essere modificate dalla procedura sono quelle
incluse nella lista di variabili.
4
Esempio
Problema: Calcolo dell’ area di una Corona Circolare
r1
r2
AreaCorona = A1 – A2
A1= Area del cerchio di raggio r1;
A2= Area del cerchio di raggio r2.
Lo stesso sottoproblema, che consiste nel calcolo dell’ area
di un cerchio di raggio noto, si ripete due volte.
5
Esempio di codice Fortran
per il Calcolo dell’Area di una Corona Circolare
PROGRAM Corona_Circolare
REAL,PARAMETER:: pi= 3,1415926
REAL:: r1, r2, area1, area2, corona
…….
READ (*,*) r1, r2
area1= pi x r1 x r1
area2 = pi x r2 x r2
corona = area1-area2
Write(*,*) corona
END PROGRAM
Osservazione :
Il calcolo dell’area di un cerchio si ripete due volte, per valori diversi dei dati
6
Tale calcolo (area di un cerchio) potrebbe essere codificato come
un programma indipendente da eseguire più volte. I valori forniti
dalle due esecuzioni potrebbero essere messi in Input al programma
CORONA
OPPURE:
Può essere costruita una procedura per il calcolo
dell’area di un cerchio: questa procedura potrà essere
richiamata dal programma principale Corona due
volte: una prima volta per effettuare il calcolo dell’area
del cerchio esterno e una seconda volta per il calcolo
dell’area del cerchio interno.
Program Corona
area A1
area A2
Procedura area_cerchio
return
end
L’algoritmo per il calcolo dell’area del cerchio viene codificato una sola volta e
viene richiamato dall’algoritmo principale ogni volta che necessita eseguirlo
tale calcolo .
8
Regole per la comunicazione tra le due unità di programma
La lista dei parametri costituisce il canale di comunicazione tra
l’algoritmo principale e la procedura.
-- Vi deve essere una perfetta corrispondenza in numero ed in
tipo tra le due liste: quella dei parametri attuali e quella dei
parametri formali
-- La corrispondenza tra i singoli parametri nelle due liste è per
posizione nell’ambito della lista
Nell’algoritmo chiamante
call area_cerchio (r1, area1)
parametri attuali
Nella procedura richiamata
procedura area_cerchio(raggio, area)
parametri formali
Strumenti Fortran per la realizzazione di procedure
Il Fortran dispone di due tipi di procedure
Subroutine
--Può restituire più valori
--E’ richiamata con una istruzione
Function
--Restituisce un singolo valore
-- E’ richiamata con il suo nome
10
PASSAGGIO DEI PARAMETRI : La corrispondenza tra i parametri attuali e quelli
formali si realizza tramite il passaggio dell’indirizzo di memoria del parametro
attuale al sottoprogramma chiamato che, mentre è in esecuzione, lo usa come
indirizzo del corrispondente parametro formale.
Nel codice
…
CALL subroutine ( Aattuale , Battuale)
…
…
subroutine ( Aformale , Bformale)
…
memoria
Aattuale
Battuale
10101010
10111010
Quando la
esecuzione:
Aformale
Bformale
subroutine
Aformale corrisponde
alla
va
in
stessa
locazione di memoria di Aattuale
e
Bformale corrisponde alla stessa
locazione di memoria Battuale
11
PASSAGGIO DEI PARAMETRI - se il parametro è un array :
Attraverso il nome dell’array viene passato alla procedura
l’indirizzo dell’array cioè, come sappiamo, l’indirizzo della
prima componente.
L’indirizzo della prima componente del parametro formale
coinciderà con l’indirizzo della prima componente di
quello attuale
Le altre componenti dell’array, essendo memorizzate nelle
locazioni consecutive, si corrispondono automaticamente.
12
PASSAGGIO DEI PARAMETRI - se il parametro è un array :
RICORDA !
Bisogna prestare particolare attenzione a quante sono le
componenti dell’array per il programma chiamante e quante
sono per il sottoprogramma !
Per gli array bidimensionali bisogna tener conto anche di come
sono memorizzate le componenti (ad es in Fortran: per
colonne) in Fortran è vitale far in modo che coincidano la
dimensione di una colonna dell’array cosi come è dichiarato nel
programma chiamante e quella con cui è dichiarato nella
procedura. Ciò è indispensabile affinchè coincidano gli indirizzi
dei singoli elementi dell’array…
13
La Subroutine: chiamata
Una subroutine è una procedura che viene invocata per
mezzo di una specifica istruzione :
CALL nome_subroutine (lista_parametri_attuali)
Il programma chiamante fornisce i valori di input alla
subroutine e riceve i valori di output dalla subroutine
attraverso la lista dei parametri attuali.
14
La Subroutine: struttura
Una subroutine è un’unità di programma Fortran che assume la
forma seguente:
SUBROUTINE nome_subroutine (lista_parametri_formali)
…
(sezione dichiarativa)
…
(sezione esecutiva)
RETURN
END SUBROUTINE nome_subroutine
15
La Subroutine: struttura– l’attributo INTENT
SUBROUTINE sub( var1, var2, sum, volte)
REAL , INTENT (IN) :: var1, var2
REAL , INTENT (OUT) :: sum
INTEGER, INTENT (INOUT) :: volte
sum = var1 + var2
volte = volte +1
RETURN
16
La Subroutine: struttura (variabili locali)
SUBROUTINE acerc( r, a)
REAL , INTENT (IN) :: r
REAL , INTENT (OUT) :: a
REAL, PARAMETER :: pi = 3.14
a = pi * ( r * r)
RETURN
Parametri della subroutine
costante LOCALE alla
subroutine
17
La Subroutine: esempio chiamata
Programma chiamante
Program Corona
Subroutine
SUBROUTINE CIRC (RAG, AREA)
CALL CIRC(R1,A1)
CALL CIRC(R2,A2)
end
REAL, INTENT(IN) :: RAG
REAL; INTENT (OUT) :: AREA
RETURN
La Function: chiamata
Una function è una procedura che viene invocata per
mezzo del suo nome, e non con una specifica istruzione.
var = nome_function (lista_parametri_attuali)
Una ‘chiamata a function’, o ‘riferimento a function’ dal
punto di vista della teoria dei linguaggi formali, è un
“primario”, cioè è della stessa natura di una costante o di
una variabile semplice, dunque può comparire nel
programma ovunque potrebbe comparire una variabile
semplice.
La Function: struttura (1)
tipo FUNCTION nome_function (lista_parametri)
…
(sezione dichiarativa)
…
(sezione esecutiva)
nome_function = ……..
…..
RETURN
END FUNCTION [nome_function]
20
La Function: struttura
 Nell’unità di programma ‘function’, il nome della function viene usato
come nome di una variabile del tipo dichiarato nella intestazione della
function;
 Tale variabile deve comparire almeno una volta a sinista dell’uguale in
una frase di assegnazione, cioè a tale variabile deve essere sempre
assegnato un valore durante l’esecuzione della function;
 Al termine della esecuzione della function il valore di tale variabile è il
‘valore della function’, cioè il valore restituito al programma chiamante;
 L’istruzione return restituisce il controllo al programma chiamante nel
punto in cui è stata chiamata la function, cioè nel punto esatto in cui
compare il riferimento alla function.
La Function: esempio
Programma chiamante
Program Corona
Sottoprogramma di tipo function
REAL FUNCTION CIRC(RAG)
A1=CIRC(R1)
A2=CIRC(R2)
end
CIRC= pi * r *r
END FUNCTION CIRC
22
INTRINSIC FUNCTIONS ( funzioni intrinseche)
 Ogni linguaggio di programmazione fornisce un insieme di
functions predefinite (intrinseche) a cui è possibile far
riferimento, nelle espressioni, senza doverle riscrivere
 Il codice che implementa queste funzioni è messo a
disposizione, in forma precompilata e quindi rilocabile, sotto
forma di librerie
 Le librerie (purchè presenti sul disco)
vengono linkate
automaticamente insieme al programma chiamante dal
relocating loader.
Funzioni Intrinseche del Fortran
 Di natura specificamente matematica
SIN (X), COS(X), SQRT(X)…..
EXP(X) , LOG(X)….
 Di carattere generale
MOD(X,Y), MIN(A,B), MAX(A,B)….
 Di utilità
CHAR… SHIFT… funzioni per uso di puntatori… ecc. ecc.
 Di utilità : chiamate ad una routine del sistema operativo
Come ad es. CPU_Time(x) , second(x)
Uso della subroutine ‘cpu_time’
program test_cpu_time
real :: start, finish , time
call cpu_time(start)
….
! Codice fortran da temporizzare
……
call cpu_time(finish)
time = finish – start
write)(*,*) "Tempo impiegato: ", time , " secondi”
end program test_cpu_time
25
FINE SUBROUTINES /FUNCTIONS
IN FORTRAN
26
ESEMPI
27
Prodotto scalare
di due vettori :
flow_chart
start
n
a i ,i = 1, n
bi ,i = 1, n
sca = 0
i=0
i= i+1
sca = sca + a i * bi
i == n
FALSO
VERO
sca
stop
Laboratorio di Prgrammazione
Prof_A.C.Simoncelli a.a. 2011/12
28
PRODOTTO SCALARE TRA DUE VETTORI
PROGRAM scalare
IMPLICIT NONE
INTEGER, parameter :: n = 10 ! dim. comune
INTEGER :: i
REAL :: sca
REAL, DIMENSION (n) :: vett1 = 0., vett2 = 0.
! creo i due vettori
elem_i: DO i=1, n
vett1(i) = i
vett2(i) = 1
END DO elem_i
! calcolo del prodotto scalare vett1 X vett2
sca = 0.
accumulo : DO i=1, n
sca = sca + vett1(i) * vett2(i)
END DO accumulo
!output
WRITE(*,*) ' Il prodotto scalare dei vettori'
WRITE(*,*)
WRITE(*,100) 'vett1 =', (vett1(i), i=1,n)
WRITE(*,100) 'vett2 =', (vett2(i), i=1,n)
WRITE(*,*) 'e'' il numero: ' , sca
100 FORMAT ( A8 , 10f5.0)
STOP
END PROGRAM scalare
ESECUZIONE :
C:\MyFor\STUDENTI\ASS_19_11>scalare
Il prodotto scalare dei vettori
vett1 = 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
vett2 = 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
e' il numero: 55.
C:\MyFor\STUDENTI\ASS_19_11>
Laboratorio di Prgrammazione
Prof_A.C.Simoncelli a.a. 2011/12
29
start
Prodotto di due
matrici, righe per colonne:
flow_chart
nria, ndimcom, ncob
a ij ; i = 1, nria ; j = 1, ndimcom
bij ; i = 1, ndimcom; j = 1, ncob
i=0
i=i+1
j=0
sca = 0
j= j+ 1
k=0
Calcola l’elemento pij della matrice prodotto:
pij = prodotto scalare riga-a i X colonna-bj
k= k+1
sca = sca + a ik * bkj
FALSO
j==ncob
k == ndimcom
FALSO
VERO
VERO
FALSO
p i j = sca
i ==nria
VERO
pij ; i = 1, nria ; j = 1, ncob
stop
Laboratorio di Prgrammazione
Prof_A.C.Simoncelli a.a. 2011/12
30
PRODOTTO DI DUE MATRICI di dimensioni compatibili
PROGRAM matmat
! Crea due matrici di dimensioni compatibili (m X n) , (n x k)
! e ne calcola il prodotto di
IMPLICIT NONE
! dimensione comune = ncom
INTEGER,parameter :: ncom = 4 , nri1 = 2, nco2 = 3
INTEGER :: i,j,k
REAL :: sca !var. appoggio per accumulo somma
REAL, DIMENSION (nri1, ncom) :: mat1 = 0.
REAL, DIMENSION (ncom, nco2) :: mat2 = 0.
REAL, DIMENSION (nri1, nco2) :: matprod = 0.
!---------------creazione prima matrice
rigam1_i: DO i=1, nri1
elemento1_ij : DO j = 1, ncom
mat1(i,j) = 2*i + j
END DO elemento1_ij
END DO rigam1_i
!---------------creazione seconda matrice
rigam2_i: DO i=1, ncom
elemento2_ij : DO j = 1, nco2
mat2(i,j) = j
END DO elemento2_ij
END DO rigam2_i
!------- calcolo elementi del prodotto
!-------matprod = mat1 X mat2
rigapro_i: DO i = 1, nri1
elepro_ij: DO j=1, nco2
sca = 0.
accumulo: DO k=1, ncom
sca = sca + mat1(i,k) * mat2(k,j)
END DO accumulo
matprod(i,j)= sca
END DO elepro_ij
END DO rigapro_i
!-----------------output
WRITE(*,*) ' Il prodotto della matrice di dimensione', nri1,'x',ncom
printriga: DO i=1, nri1
WRITE(*,100) (mat1(i,j),j = 1,ncom)
END DO printriga
WRITE(*,*) ' per la matrice di dimensione', ncom,'x',nco2
printri: DO i=1, ncom
WRITE(*,100) (mat2(i,j),j = 1,nco2)
END DO printri
WRITE(*,*) 'e'' la matrice di dimensione', nri1,'x',nco2
printlinea: DO i=1, nri1
WRITE(*,100) (matprod(i,j),j = 1,nco2)
END DO printlinea
100 FORMAT ( 2x, 10f5.0)
STOP
END PROGRAM matmat
Laboratorio di Prgrammazione
Prof_A.C.Simoncelli a.a. 2011/12
31
Si potrebbe scrivere un programma per il calcolo
del prodotto righe per colonne in cui il prodotto
scalare necessario per calcolare ogni elemento
del prodotto non viene codificato all’interno del
programma ma viene scritto sotto forma di
procedura e richiamato dal programma
principale ogni volta che è necessario….
32
UN ESEMPIO UN PO’ PIU’ COMPLESSO
Progettiamo ed implementiamo un programma
Fortran che sia in grado di verificare la validità
della nota relazione per le matrici trasposte:
(A x B ) T = B T x A T
controllando che essa sussista per qualsiasi
coppia di matrici A e B fornite in input, del tutto
arbitrarie purché di dimensioni compatibili.
33
Diagramma a grossi blocchi
start
Leggi matrici
A, B
Calcola C = A x B
maxel
== 0
vero
falso
Calcola CT= trasposta di C
Scrivi
‘NON VERIFICATA’
Calcola AT = trasposta di A
Calcola BT = trasposta di B
Calcola PT = BT x AT
Scrivi
‘VERIFICATA’
Calcola DIFF = CT - PT
Calcola ADIFF = ABS(DIFF)
Calcola maxel = massimo
elemento di ADIFF
stop
34
UNA SUBROUTINE PER CALCOLARE LA
TRASPOSTA DI UNA MATRICE
SUBROUTINE TRASP (D,dmaxdim,drighe,dcolonne,DT)
INTEGER, INTENT(IN) :: dmaxdim, drighe, dcolonne
INTEGER :: i, j
REAL, DIMENSION (dmaxdim,dmaxdim), INTENT(IN) :: D
REAL, DIMENSION (dmaxdim,dmaxdim), INTENT(OUT) :: DT
DO i = 1, dcolonne
DO j = 1, drighe
DT(i,j) = D(j,i)
END DO
END DO
RETURN
END SUBROUTINE TRASP
35
UNA SUBROUTINE PER CALCOLARE IL
PRODOTTO DI DUE MATRICI
SUBROUTINE PROD (MA,maxdima,MB,maxdimb, arighe,acolonne,brighe,bcolonne,PP,maxdimp, ok)
INTEGER , INTENT(IN) :: maxdima, maxdimb, maxdimp, arighe , acolonne , brighe , bcolonne
LOGICAL, INTENT(OUT) :: ok
REAL, DIMENSION(maxdima,maxdima), INTENT(IN) :: MA, MB
REAL, DIMENSION (maxdimp,maxdimp), INTENT(OUT) :: PP
INTEGER :: i, j, k ! variabili locali - contatori
REAL :: app ! variabile locale per accumulo prodotto scalare
IF ( acolonne == brighe) THEN ! si puo' calcolare il prodotto
ok = .TRUE.
DO i = 1, arighe
DO j = 1, bcolonne
app = 0.
DO k = 1, acolonne
app = app + MA(i,k)* MB(k,j)
END DO
PP(i,j) = app
END DO
END DO
ELSE ! dimensioni effettive incompatibili: impossibile calcolare il prodotto
ok = .FALSE.
ENDIF
RETURN
END SUBROUTINE PROD
36
UNA SUBROUTINE PER CALCOLARE LA
SOMMA DI DUE MATRICI
SUBROUTINE SUMMAT (M1,M2,dimassima,nrighe,ncolonne,SUM)
INTEGER, INTENT(IN) :: dimassima, nrighe, ncolonne
INTEGER :: i, j
REAL, DIMENSION (dimassima,dimassima), INTENT(IN) :: M1,M2
REAL, DIMENSION (dimassima,dimassima), INTENT(OUT) :: SUM
rigai: DO i = 1, nrighe
elementoij: DO j = 1, ncolonne
SUM(i,j) = M1(i,j) + M2(i,j)
END DO elementoij
END DO rigai
RETURN
END SUBROUTINE SUMMAT
37
UNA FUNCTION PER TROVARE IL
MASSIMO ELEMENTO DI UNA MATRICE
REAL FUNCTION MAXMAT (mat,maxdim,nrim,ncom)
INTEGER, INTENT(IN) :: maxdim,nrim,ncom
INTEGER :: i, j
REAL, DIMENSION (maxdim,maxdim), INTENT(IN) :: mat
maxmat = mat(1,1)
rigai: DO i = 1, nrim
elementoij: DO j = 1, ncom
IF (mat(i,j) > maxmat) maxmat = mat(i,j)
END DO elementoij
END DO rigai
RETURN
END FUNCTION MAXMAT
38
Il nostro MAIN : solo uno dei possibili programmi per implementare
l’algoritmo utilizzando tutte le precedenti procedure
PROGRAM matrix
IMPLICIT NONE
! dichiarazione delle costanti e delle variabili
INTEGER, PARAMETER :: maxdim = 20
REAL, DIMENSION (maxdim, maxdim) :: A, B, AT, BT
REAL, DIMENSION (maxdim, maxdim) :: PR, PRT, PRATBT
REAL, DIMENSION (maxdim, maxdim) :: DIFF
INTEGER :: nria, ncoa, nrib, ncob
INTEGER :: i, j, ierror
LOGICAL :: ok
REAL :: maxel, maxmat
… continua
39
Il nostro MAIN ….. continua
! INPUT DATI E VERIFICA
OPEN (UNIT = 8, FILE = 'mata', STATUS = 'OLD', ACTION = 'READ', IOSTAT = ierror)
READ(8,*) nria, ncoa
rrigaa : DO i = 1, nria
READ(8,*) ( A(i,j), j = 1, ncoa)
END DO rrigaa
CLOSE(8)
! Echo
WRITE (*,*)
WRITE (*,*) ' Matrice A : ' , nria, 'righe,', ncoa, 'colonne'
wrigaa : DO i = 1 , nria
WRITE(*,*) ( A(i,j), j = 1, ncoa)
END DO wrigaa
OPEN (UNIT = 8, FILE = 'matb', STATUS = 'OLD', ACTION = 'READ', IOSTAT = ierror)
READ(8,*) nrib, ncob
rrigab : DO i = 1 , nrib
READ(8,*) ( B(i,j), j = 1, ncob)
END DO rrigab
CLOSE(8)
WRITE (*,*)
WRITE (*,*) ' Matrice B: ' , nrib, 'righe,', ncob, 'colonne'
wrigab : DO i = 1 , nrib
WRITE(*,*) ( B(i,j), j = 1, ncob)
END DO wrigab
40
Il nostro MAIN ….. continua
! Calcola matrice prodotto
CALL PROD (A,maxdim,B,maxdim,nria,ncoa,nrib,ncob,PR,maxdim, ok)
WRITE (*,*) ok
IF ( ok) THEN
WRITE (*,*)
WRITE (*,*) ' Matrice prodotto di A x B' , nria, 'righe,', ncob, 'colonne'
wrigap : DO i = 1 , nria
WRITE(*,100) ( PR(i,j), j = 1, ncob)
END DO wrigap
ENDIF
! Calcola le tre trasposte
CALL TRASP (A,maxdim,nria,ncoa,AT)
CALL TRASP (B,maxdim,nrib,ncob,BT)
CALL TRASP (PR,maxdim,nria,ncob,PRT)
! Calcola il prodotto delle trasposte
CALL PROD (BT,maxdim,AT,maxdim,ncob,nrib,ncoa,nria,PRATBT,maxdim, ok)
41
Il nostro MAIN ….. continua
! Calcola la matrice differenza
CALL SUMMAT (PRT, -PRATBT, maxdim,ncob,nria,DIFF)
! Calcola il massimo tra I valori assoluti degli elementi della matrice
maxel = MAXMAT (ABS(DIFF),maxdim,ncob,nria)
WRITE (*,*) 'massimo valore assoluto', maxel
! Finalmente : il controllo è effettuato su maxel
IF (maxel == 0. ) THEN
WRITE (*,*) 'La relazione risulta verificata: (AxB)t = Bt x At'
ELSE
WRITE (*,*) 'In questo caso la relazione (AxB)t = Bt x At non risulta verificata:'
END IF
STOP
100 FORMAT ( 1x, 20F8.2 )
END PROGRAM matrix
42
Ora bisogna eseguirlo !
Aprire il terminale e cominciare a lavorare 
43
FINE (22.5.2012)
44
Scarica