Il linguaggio Fortran 90:
4. Array: Vettori e Matrici
1
Vettori
• Gruppi di variabili dello stesso tipo memorizzate
in locazioni contigue di memoria.
• La i-esima posizione dell’array a è indicata con
a(i)
a(1) a(2) a(3) a(4) a(5)
• Gli elementi di un array sono normali variabili
2
Dichiarazione di variabili vettore
• REAL, DIMENSION (20) :: a
L’attributo DIMENSION serve per dichiarare la lunghezza del vettore
• CHARACTER(len=20), DIMENSION (50) :: cognome
Indica un vettore di 50 elementi ognuno dei quali è una stringa di 20
caratteri
• Costanti di tipo array:
(/ 1, 2, 3, 4, 5 /)
• Inizializzazione di un array:
INTEGER, DIMENSION (5) :: a = (/ 1, 2, 3, 4, 5
/)
• DO i=1, 5
a(i)=i
END DO
• Il range di variabilità può essere fissato
altrimenti:
REAL DIMENSION (inf : sup) :: a
3
Somma di due vettori
! File: somvett1.for
! Scopo: esempio di uso di array
PROGRAM somma_vettori
! Questo programma calcola la somma di due vettori a 3 componenti
! *** SEZIONE DICHIARATIVA *** !
IMPLICIT NONE
INTEGER, PARAMETER :: dimensione = 3
INTEGER, DIMENSION(dimensione) :: v1, v2
! i due vettori letti
INTEGER, DIMENSION(dimensione) :: somma
! il vettore somma
INTEGER :: i
! indice di ciclo per scandire le componenti dei vettori
! *** SEZIONE ESECUTIVA *** !
! lettura primo vettore
WRITE(*,*) 'Immetti il primo vettore!'
DO i = 1, dimensione
! leggiamo il vettore una componente alla volta
WRITE(*,*) 'Componente ', i, ' ? '
READ (*,*) v1(i)
END DO
4
Somma di due vettori (cont.)
! lettura secondo vettore
WRITE(*,*) 'Immetti il secondo vettore!'
DO i = 1, dimensione
! leggiamo il vettore una componente alla volta
WRITE(*,*) 'Componente ', i, ' ? '
READ (*,*) v2(i)
END DO
! calcolo vettore somma
DO i = 1, dimensione
somma(i) = v1(i) + v2(i)
! N.B. si potrebbe fare direttamente somma = v1 + v2
END DO
! stampa del vettore somma
WRITE(*,*) 'Il vettore somma e'':'
DO i = 1, dimensione
WRITE(*,*) 'Componente ', i, ' : ', somma(i)
END DO
STOP
END PROGRAM somma_vettori
5
Passaggio di Parametri Vettore
• Array fittizi di forma presunta
Una procedura non conosce in generale la dimensione dei
parametri effettivi array passati alla procedura
• Array fittizi non specificano la dimensione dell’array
• REAL, DIMENSION (:) :: a
INTEGER :: i
DO i = LBOUND (a,1), UBOUND (a,1)
a (i) = 0
END DO
• In alternativa occorre passare come
parametro la dimensione degli array
6
Passaggio di Parametri di Tipo Vettore
! File: util-vet.for
MODULE operazioni_su_vettori
! Questo modulo contiene alcune unita‘ che effettuano operazioni su
! Vettori:
! - leggi_vettore : subroutine per la lettura di un vettore di interi
!
di lunghezza arbitraria
! - stampa_vettore : subroutine per la stampa di un vettore di interi
!
di lunghezza arbitraria
! - somma_vettori : funzione per la somma vettoriale di due vettori di
!
interi di lunghezza arbitraria (passata come parametro)
! - somma_vettori_sub : subroutine per la somma vettoriale di due
!
vettori di interi di lunghezza arbitraria. Analoga alla precedente
!
ma non e' necessario passare la lunghezza.
CONTAINS
7
Passaggio di Parametri di Tipo Vettore (cont.)
SUBROUTINE leggi_vettore (vet)
IMPLICIT NONE
! ** DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, INTENT(IN OUT), DIMENSION(:) :: vet
! il vettore di input
! ** DICHIARAZIONE VARIABILI LOCALI
INTEGER :: i
! indice di ciclo
DO i = LBOUND(vet,1), UBOUND(vet,1)
WRITE(*,*) 'Componente ', i, ' ? '
READ (*,*) vet(i)
END DO
RETURN
END SUBROUTINE leggi_vettore
8
Passaggio di Parametri di Tipo Vettore (cont.)
SUBROUTINE stampa_vettore (vet)
! DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, DIMENSION(:), INTENT(IN) :: vet
! Vettore di input
! DICHIARAZIONE VARIABILI LOCALI
INTEGER :: i
! indice del ciclo
DO i = LBOUND(vet,1), UBOUND(vet,1)
WRITE(*,*) 'Componente ', i, ':', vet(i)
END DO
RETURN
END SUBROUTINE stampa_vettore
9
Passaggio di Parametri di Tipo Vettore (cont.)
FUNCTION somma_vettori (vet1, vet2, dim)
IMPLICIT NONE
! ** DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2
! i vettori di input
INTEGER, INTENT(IN) :: dim
! la lunghezza dei vettori
! ** DICHIARAZIONE TIPO FUNZIONE
INTEGER, DIMENSION(dim) :: somma_vettori
! ** DICHIARAZIONE VARIABILI LOCALI
INTEGER :: i
! indice del ciclo
DO i = LBOUND(vet1,1), UBOUND(vet1,1)
somma_vettori(i) = vet1(i) + vet2(i)
END DO
RETURN
END FUNCTION somma_vettori
10
Passaggio di Parametri di Tipo Vettore (cont.)
SUBROUTINE somma_vettori_sub (vet1, vet2, ris)
IMPLICIT NONE
! ** DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2
! i vettori di input
INTEGER, DIMENSION(:), INTENT(OUT) :: ris
! il vettore di output
INTEGER :: i
! indice del ciclo
! *** SEZIONE ESECUTIVA
DO i = LBOUND(vet1,1), UBOUND(vet1,1)
ris(i) = vet1(i) + vet2(i)
END DO
RETURN
END SUBROUTINE somma_vettori_sub
11
Passaggio di Parametri di Tipo Vettore (cont.)
! File: somvett2.for
! Scopo: Uso di sottoprogrammi che manipolano array unidimensionali di
! due vettori a 3 componenti, usando le SUBROUTINE
PROGRAM somma_vettori_2
! *** SEZIONE DICHIARATIVA *** !
USE operazioni_su_vettori
IMPLICIT NONE
INTEGER, PARAMETER :: dimensione = 3
INTEGER, DIMENSION(dimensione) :: v1, v2
! i due vettori letti
INTEGER, DIMENSION(dimensione) :: somma
! il vettore somma
12
Passaggio di Parametri di Tipo Vettore (cont.)
! *** SEZIONE ESECUTIVA *** !
WRITE(*,*) 'Immetti il primo vettore!'
CALL leggi_vettore(v1)
! lettura secondo vettore
WRITE(*,*) 'Immetti il secondo vettore!'
CALL leggi_vettore(v2)
! calcolo vettore somma con la funzione
somma = somma_vettori(v1,v2,dimensione)
! stampa del vettore somma
WRITE(*,*) 'Il vettore somma e'':'
CALL stampa_vettore(somma)
! calcolo vettore somma con la subroutine
CALL somma_vettori_sub(v1,v2,somma)
! stampa del vettore somma
WRITE(*,*) 'Il vettore somma (calcolato in altra maniera) e'':'
CALL stampa_vettore(somma)
STOP
END PROGRAM somma_vettori_2
13
Ordinamento di un Vettore
• Ordinare un vettore di n interi in modo non
decrescente.
10
6
12
3
1
1
3
6
10
12
14
Algoritmo di Ordinamento
loop1: DO i=1, n-1
“Tova la posizione k_min del
minimo intero nelle posizioni
da i a n”
“Scambia l’elemento nella
posizione i con l’elemento
nella posizione k_min”
END DO loop1
15
Ordinamento di un Vettore (Cont.)
“Trova la posizione k_min del minimo intero
nelle posizioni da i a n”
k_min = i
loop2: DO j=i+1, n
IF (a(j) < a(k_min)) k_min = j
END DO loop2
“Scambia l’elemento nella posizione i con
l’elemento nella posizione k_min”
tmp = a(i)
a(i) = a(kmin)
a(kmin) = tmp
16
Ordinamento di un Vettore (Cont.)
SUBROUTINE ordinavett(v)
! Scopo: ordinamento di un vettore di interi
IMPLICIT NONE
! Dichiarazione parametri formali
INTEGER, DIMENSION (:), INTENT (IN OUT) :: v
! Dichiarazione variabili locali
INTEGER :: i, j, k_min, i_min, i_max, tmp
i_min = LBOUND(v,1)
i_max = UBOUND(v,1)
loop1: DO i=i_min, (i_max - 1)
k_min = i
loop2: DO j=i+1, i_max
IF (v(j) < v(k_min)) k_min = j
END DO loop2
tmp = v(i)
v(i) = v(k_min)
v(k_min) = tmp
END DO loop1
RETURN
END SUBROUTINE ordinavett
17
Ordinamento di un Vettore (Cont.)
! File: test_ordinavett.for
! Scopo: testare la subroutine ordinavett(v) che ordina un vettore di interi
PROGRAM test_ordinavett
USE operazioni_su_vettori
IMPLICIT NONE
INTEGER, PARAMETER :: dimensione = 3
INTEGER, DIMENSION(dimensione) :: v
! vettore da leggere e ordinare
WRITE(*,*) 'Immetti il vettore di interi da ordinare '
CALL leggi_vettore(v)
! stampa del vettore inserito
WRITE(*,*) 'Vettore inserito: '
CALL stampa_vettore(v)
! ordino il vettore somma con la funzione ordinavett(v)
CALL ordinavett(v)
! stampa del vettore ordinato
WRITE(*,*) 'Vettore ordinato: '
CALL stampa_vettore(v)
STOP
END PROGRAM test_ordinavett
18
Matrici
• Vettori a due dimensioni
• Ogni elemento è indicato da un indice di riga ed un indice
di colonna
• L’elemento della matrice di indice di riga i ed indice di
colonna j è indicato con a(i,j)
1
2
3
4
5
1
2
3
4
19
Dichiarazione di Matrici
• INTEGER, DIMENSION (5,10) :: a
• REAL, DIMENSION (0:100, 5:20) :: valori
• Inizializzazione di una Matrice
INTEGER, DIMENSION (7,10) :: mat
DO i=1, 7
DO j=1, 10
mat(i,j) = 0
END DO
END DO
20
Gestione delle matrici
! File: mod_matr.for
MODULE modulo_matrici
! Questo modulo contiene alcune unita‘ che effettuano operazioni su
! matrici:
! - leggi_matrice : subroutine per la lettura di una matrice
!
bidimensionale di interi di forma arbitraria
! - stampa_matrice : subroutine per la stampa di una matrice
!
bidimensionale di interi di forma arbitraria
! - somma_matrici : funzione per la somma vettoriale di due matrici
!
bidimensionali di interi di forma arbitraria
! - prodotto_matrici : funzione che calcola il prodotto di due
!
matrici di interi
CONTAINS
21
Gestione delle matrici (cont)
SUBROUTINE leggi_matrice (mat)
IMPLICIT NONE
! ** DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, INTENT(IN OUT), DIMENSION(:,:) :: mat
! ** DICHIARAZIONE VARIABILI LOCALI
INTEGER :: i, j, r_min, r_max, c_min, c_max
r_min
r_max
c_min
c_max
=
=
=
=
LBOUND
UBOUND
LBOUND
UBOUND
! matrice di input
(mat,1)
(mat,1)
(mat,2)
(mat,2)
WRITE(*,*) 'Inserisci matrice', (r_max-r_min+1), ' *',(c_max-c_min+1)
DO i = r_min, r_max
DO j = c_min, c_max
WRITE(*,*) 'componente ', i, j, ' : '
READ (*,*) mat(i,j)
END DO
END DO
RETURN
END SUBROUTINE leggi_matrice
22
Gestione delle matrici (cont)
SUBROUTINE stampa_matrice (mat)
IMPLICIT NONE
! ** DICHIARAZIONE ARGOMENTI FITTIZI
INTEGER, INTENT(IN), DIMENSION(:,:) :: mat ! matrice di input
! ** DICHIARAZIONE VARIABILI LOCALI
INTEGER :: i, j, r_min, r_max, c_min, c_max
r_min
r_max
c_min
c_max
=
=
=
=
LBOUND
UBOUND
LBOUND
UBOUND
(mat,1)
(mat,1)
(mat,2)
(mat,2)
DO i = r_min, r_max
WRITE(*,*) 'riga', i
DO j = c_min, c_max
WRITE(*,*) '
col.', j, ' =', mat(i,j)
END DO
END DO
RETURN
END SUBROUTINE stampa_matrice
23
Somma di Matrici
SUBROUTINE somma_matrici(a, b, c)
IMPLICIT NONE
! Dichiarazioni parametri fittizi
INTEGER, DIMENSION(:,:), INTENT (IN) :: a, b
INTEGER, DIMENSION (:,:),INTENT (OUT) :: c
! Dichiarazione variabili locali
INTEGER :: i, j, r_min, r_max, c_min, c_max
r_min
r_max
c_min
c_max
=
=
=
=
LBOUND
UBOUND
LBOUND
UBOUND
(a,1)
(a,1)
(a,2)
(a,2)
DO i = r_min, r_max
DO j = c_min, c_max
c(i,j) = a (i,j) + b (i,j)
END DO
END DO
RETURN
END SUBROUTINE somma_matrici
24
Moltiplicazione tra Matrici
• Date due matrici a(n:m) e b(m:p) calcolare la
matrice prodotto c(n:p).
DO i=1, n
DO j=1, p
m
c(i,j)   a(i,k) b(k,j)
k1
END DO
END DO
25
Moltiplicazione tra Matrici (cont.)
SUBROUTINE prodotto_matrici (a,b,c,n,m,p)
IMPLICIT NONE
! Dichiarazioni parametri
INTEGER, INTENT(IN) :: n,
INTEGER, DIMENSION (n,m),
INTEGER, DIMENSION (m,p),
INTEGER, DIMENSION (n,p),
! Dichiarazione variabili
INTEGER :: i, j, k
formali
m, p
INTENT (IN) :: a
INTENT (IN) :: b
INTENT (OUT) :: c
locali
DO i = 1, n
DO j = 1, p
c(i,j) = 0
DO k = 1, m
c(i,j) = c(i,j) + a(i,k) * b(k,j)
END DO
END DO
END DO
RETURN
END SUBROUTINE prodotto_matrici
26
Calcolo del minimo locale
• Data una matrice a(n:m) calcolare per ogni
elemento a(i,j) il minimo tra a(i,j) e gli
elementi adiacenti.
a
2 10 6
12 3 5
1 3 6
b

1
27
Calcolo del minimo locale (cont.)
SUBROUTINE minimo_locale(a,b,n,m)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n, m
INTEGER, DIMENSION(n,m), INTENT (IN) :: a
INTEGER, DIMENSION (n,m),INTENT (OUT) :: b
! Dichiarazione variabili locali
INTEGER :: i, j, k, l, i1,i2, j1, j2,min
IF ((n < 2) .OR. (m < 2)) THEN
b = a
ELSE
loop1: DO i = 1, n
loop2: DO j = 1, m
“Calcolo del minimo locale nell’intorno
di a(i,j) ed assegnazione a b(i,j)”
END DO loop2
END DO loop1
END IF
RETURN
END SUBROUTINE minimo_locale
END MODULE modulo_matrici
28
Calcolo del minimo locale (cont.)
“Calcolo del minimo locale nell’intorno di a(i,j)”:
IF (i == 1)
i1 = 1
ELSE
i1 = i-1
END IF
IF (i == n)
i2 = n
ELSE
i2 = i+1
END IF
IF (j == 1)
j1 = 1
ELSE
j1 = j-1
END IF
IF (j == m)
j2 = m
ELSE
j2 = j+1
END IF
THEN
THEN
THEN
THEN
29
Calcolo del minimo locale (cont.)
min = a(i,j)
loop3: DO k = i1, i2
loop4: DO l = j1, j2
IF (a(k,l) < min) min = a(k,l)
END DO loop4
END DO loop3
b(i,j) = min
30
Potenza elettrica erogata
• Per ogni istante di tempo si conosce la potenza
elettrica erogata da n generatori.
• L’osservazione delle potenza erogata prosegue per
m istanti di tempo
• Scrivere una SUBROUTINE che calcoli la
potenza media erogata da ogni generatore lungo
gli m istanti di tempo ed una SUBROUTINE che
calcoli la potenza totale erogata dagli n generatori
ad ogni istante di tempo
31
Potenza elettrica erogata(cont.)
• I dati di input alla procedura sono
rappresentati in una matrice di reali
erogati(n,m) di n righe ed m colonne.
• I dati di output sono rappresentati in un
vettore media(n) ed un vettore
totale(m)
32
Potenza elettrica erogata(cont.)
• Esempio: 4 generatori, 5 istanti di tempo
media
28.22
1
2
1
30.0
26.7
2
18.2
3
36.6
4
24.4
totale
3
4
5
24.9 28.1 31.4
119.2
33
Potenza elettrica erogata(cont.)
Calcolo della potenza media
SUBROUTINE pot_media (erogati, n, m, media)
! Scopo: calcolo della potenza media erogata da ogni generatore
! *** SEZIONE DICHIARATIVA *** !
IMPLICIT NONE
! Dichiarazione parametri formali
REAL, DIMENSION(:,:), INTENT(IN) :: erogati
INTEGER, INTENT(IN) :: n, m
REAL, DIMENSION(:), INTENT(OUT) :: media
! Dichiarazione variabili locali
INTEGER :: i,j
REAL ::temp
34
Potenza elettrica erogata(cont.)
Calcolo della potenza media
! *** SEZIONE ESECUTIVA *** !
DO i=1, n
! Calcola la potenza media del generatore i
temp = 0.
DO j=1, m
! Scandisci gli m istanti di tempo
temp = temp + erogati(i,j)
END DO
media(i) = temp / m
END DO
RETURN
END SUBROUTINE pot_media
35
Potenza elettrica erogata(cont.)
Calcolo della potenza totale
SUBROUTINE pot_totale (erogati, n, m, totale)
! Scopo: calcolo della potenza totale erogata da ogni generatore
! *** SEZIONE DICHIARATIVA *** !
IMPLICIT NONE
! Dichiarazione parametri formali
REAL, DIMENSION(:,:), INTENT(IN) :: erogati
INTEGER, INTENT(IN) :: n, m
REAL, DIMENSION(:), INTENT(OUT) :: totale
! Dichiarazione variabili locali
INTEGER :: i,j
REAL ::temp
36
Potenza elettrica erogata(cont.)
Calcolo della potenza totale
! *** SEZIONE ESECUTIVA *** !
DO i=1, m
! Calcola la potenza totale erogata al tempo i
temp = 0.
DO j=1, n
! Scandisci gli n generatori
temp = temp + erogati(j,i)
END DO
totale(i) = temp
END DO
RETURN
END SUBROUTINE pot_totale
37
Calcolo dei prodotti scalari
• Una matrice x(n:m) memorizza le componenti di n
vettori ad m dimensioni
• Scrivere una SUBROUTINE che calcoli il
prodotto scalare tra tutte le coppie di vettori
• Il risultato e’ formato di n**2 prodotti
scalari che memorizziamo in una matrice
prod (n:n)
38
Calcolo dei prodotti scalari
EX: m=3
v1 = x(1,1) i + x(1,2) j+ x(1,3) k
v2 = x(2,1) i + x(2,2) j+ x(2,3) k
v1 v2 = x(1,1) * x(2,1) + x(1,2) * x(2,2) + x(1,3)
* x(2,3)
39
Calcolo dei prodotti scalari (cont.)
SUBROUTINE prodotto_scalare (x, n, m, prod)
! Scopo: calcolo dei prodotti scalari tra tutte le coppie di n righe
! di una matrice x(n,m).
! Ritorna la matrice dei prodotti scalari prod(n,n)
! *** SEZIONE DICHIARATIVA *** !
IMPLICIT NONE
!Dichiarazione parametri formali
INTEGER, INTENT(IN) :: n, m
REAL, DIMENSION(:,:), INTENT(IN) :: x
! x(i,j) memorizza la j-ma componente dell’i-mo vettore
REAL, DIMENSION(:,:), INTENT(OUT) :: prod
! Prod(i,j) memorizza il prodotto scalare tra il vettore i ed il
! vettore j
!Dichiarazione variabili locali
INTEGER :: i, j, k
REAL :: tmp
40
Calcolo dei prodotti scalari (cont.)
! *** SEZIONE ESECUTIVA *** !
DO i = 1, n
DO j = 1, n
tmp = 0.0
DO k = 1, m
tmp = tmp + x(i,k) * x(j,k)
END DO
WRITE(*,*)'prod(',i,j,') = ',tmp
prod (i,j) = tmp
END DO
END DO
RETURN
END SUBROUTINE prodotto_scalare
41
Scarica

4. Array: Vettori e Marici