Il linguaggio Fortran 90: 2. Istruzioni di Controllo 1 Strutture di Controllo • Programmi visti in precedenza permettono di eseguire le istruzioni solo nella sequenza indicata. • La risoluzione di molti problemi richiede la scrittura di programmi in cui le azioni che si svolgono dipendono dall’input del problema. • Strutture di controllo permettono di alterare la sequenza di esecuzione delle istruzione del programma al verificarsi di determinate condizioni. • Due tipi fondamentali di istruzioni di controllo: Istruzioni Condizionali Cicli 2 Istruzioni Condizionali nome: IF (condizione) THEN istruzione 1 istruzione 2 END IF nome ________________________________ nome: IF (condizione) THEN istruzione 1 istruzione 2 ELSE istruzione 1 istruzione 2 END IF nome 3 Stampa del maggiore tra due interi !File: max.for !Scopo: primo esempio di istruzione condizionale(IF-THEN-ELSE) PROGRAM max ! Questo programma legge due numeri interi e stampa il maggiore IMPLICIT NONE INTEGER :: primo, secondo, maggiore WRITE (*,*) 'Inserisci due numeri interi, poi schiaccia il tasto RETURN' READ (*,*) primo, secondo IF (primo > secondo) THEN maggiore = primo ELSE maggiore = secondo END IF WRITE (*,*) 'Il maggiore dei due valori inseriti e'': ', maggiore STOP END PROGRAM max 4 Istruzioni condizionali nidificate. • Le istruzioni condizionali possono essere a loro volta nidificate. • Istruzione ELSE IF permette di realizzare IF annidati. nome: IF (condizione1) THEN istruzione 1 istruzione 2 ELSE IF (condizione2) THEN istruzione 1 istruzione 2 ELSE istruzione 1 istruzione 2 END IF nome 5 Classificazione dei Triangoli 1 ! File: triang1.for ! Scopo: applicazione degli IF annidati PROGRAM triangolo1 ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE REAL :: primo, secondo, terzo ! le lunghezze dei tre lati ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Inserisci le lunghezze dei tre lati del triangolo: ' READ (*,*) primo,secondo,terzo 6 Classificazione dei Triangoli 1 (cont.) if1: IF (primo == secondo) THEN if2: IF (secondo == terzo) THEN WRITE (*,*) 'Equilatero' ! I tre lati sono sono uguali fra loro ELSE WRITE (*,*) 'Isoscele' ! 1 coppia di lati uguali fra loro END IF if2 ELSE if3: IF (secondo == terzo) THEN ! primo <> secondo WRITE (*,*) 'Isoscele' ! 1 coppia di lati uguali fra loro ELSE IF (primo == terzo) THEN ! (primo <> secondo) e (secondo <> terzo) WRITE (*,*) 'Isoscele' ! 1 coppia di lati uguali fra loro ELSE WRITE (*,*) 'Scaleno' ! 0 coppie di lati uguali fra loro END IF if3 END IF if1 STOP END PROGRAM triangolo1 7 Classificazione dei Triangoli 2 • Il programma può essere semplificato scegliendo un diverso algoritmo di soluzione • If logico: IF (condizione) istruzione ! File: triang2.for PROGRAM triangolo2 ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE REAL :: primo, secondo, terzo INTEGER :: uguali ! il numero di coppie di lati uguali fra loro 8 Classificazione dei Triangoli 2 ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Inserisci le lunghezze dei tre lati del triangolo: ' READ (*,*) primo,secondo,terzo uguali = 0 IF (primo == secondo) uguali = uguali + 1 IF (secondo == terzo) uguali = uguali + 1 IF (primo == terzo) uguali = uguali + 1 IF (uguali == 0) THEN WRITE (*,*) 'Scaleno' ELSE IF (uguali == 1) THEN WRITE (*,*) 'Isoscele' ELSE WRITE (*,*) 'Equilatero' END IF STOP END PROGRAM triangolo2 9 Espressioni Logiche • Le condizioni sono espressioni logiche, possono assumere due valori di verità. • Costanti logiche: .TRUE. o .FALSE. • Variabili logiche: LOGICAL :: variabile_logica • Operatori relazionali ==, /=, >, >=, <, <= • Es: (7 + 3) /= 6 .TRUE. 10 Operatori Logici • • • • • Es: x .AND. y: x .OR. y: x .EQV. y: x .NEQV. y: .NOT. y: .TRUE. sse x e y sono .TRUE. (altrimenti .FALSE.) .TRUE. sse x o y sono .TRUE. .TRUE. sse x = y .TRUE. sse x /= y .TRUE. sse y = .FALSE. LOGICAL :: x, y, z x = .TRUE. y = .FALSE. z = (x .OR. y) .AND. (x .NEQV. y) .AND. (x /= y) = .TRUE. 11 Regole di precedenza tra operatori logici 1. 2. 3. 4. 5. 6. Operatori aritmetici Operatori relazionali da sx a dx Operatori .NOT. da sx a dx Operatori .AND. da sx a dx Operatori .OR. da sx a dx Operatori .EQV. e . NEQV. da sx a dx 12 Classificazione di triangoli 3 ! File: triang3.for PROGRAM triangolo3 IMPLICIT NONE REAL :: primo, secondo, terzo ! le lunghezze dei tre lati WRITE (*,*) 'Inserisci le lunghezze dei tre lati del triangolo: ' READ (*,*) primo,secondo,terzo IF (primo == secondo .AND. secondo == terzo) THEN WRITE (*,*) 'Equilatero' ELSE IF (primo == secondo .OR. secondo == terzo .OR. primo == terzo) THEN WRITE (*,*) 'Isoscele' ELSE WRITE (*,*) 'Scaleno' END IF STOP END PROGRAM triangolo3 13 Calcolo delle radici di un’equazione di secondo grado !File: radici.for PROGRAM radici !Scopo: Questo programma calcola le radici di un’equazione ! a*x**2+ b*x + c = 0 ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE REAL :: a, b, c REAL :: discriminante, parte_immag, parte_reale REAL :: x1, x2 ! Soluzioni dell’equazione ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Inserire i tre coeefficienti A, B e C: ' READ (*,*) a, b, c !Calcola il discriminante discriminante = b**2 - 4 * a * c 14 Calcolo delle radici di un’equazione di secondo grado (cont) ! Calcola le radici in funzione del discriminante IF (discriminante >0) THEN ! due radici reali x1 = (-b + sqrt(discriminante)) / (2.*a) x2 = (-b - sqrt(discriminante)) / (2.*a) WRITE (*,*) 'Due radici reali: ', x1, x2 ELSE IF (discriminante == 0.) THEN ! Radici reali e coincindenti x1 = ( -b ) / (2. * a) WRITE (*,*) 'due radici reali e coincidenti: ', x1 ELSE ! Radici complesse parte_reale = ( -b ) / (2. * a) parte_immag = sqrt(abs(discriminante)) / (2.*a) WRITE (*,*) 'due radici immaginarie:', parte_reale, '+/- i', parte_immag END IF STOP END PROGRAM radici 15 L’istruzione Case nome: SELECT CASE (espressione) CASE (sel 1)! Se espressione nel ! range di sel 1 istruzione 1 CASE (sel 2) ! Se espressione nel ! range di sel 2 istruzione 2 .. .. CASE DEFAULT ! In tutti gli altri casi istruzione END SELECT nome 16 Calcolo della data del giorno successivo !File: datasuc1.for !Scopo: esempio di uso dell’istruzione CASE PROGRAM data_successiva ! Questo programma legge giorno, mese ed anno di una data e determina ! la data successiva. Date possibili in ingresso: 1/1/1900 - 30/12/2000 ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER :: giorno, mese, anno ! dati in input INTEGER :: giorni_del_mese ! dato da calcolare ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Data (giorno, mese, anno)? ' READ (*,*) giorno, mese, anno WRITE (*,*) 'Il giorno successivo al', giorno, '/', mese, '/', anno, ' e'':' SELECT CASE (mese) CASE (9,4,6,11) giorni_del_mese = 30 CASE (1,3,5,7,8,10,12) giorni_del_mese = 31 17 Calcolo della data del giorno successivo (cont.) CASE (2) IF (MOD(anno,4) == 0 .AND. anno /= 1900) THEN giorni_del_mese = 29 ELSE giorni_del_mese = 28 END IF END SELECT ultimo: IF (giorno == giorni_del_mese) THEN giorno = 1 dicembre: IF (mese == 12) THEN mese = 1 anno = anno + 1 ELSE mese = mese + 1 END IF dicembre ELSE giorno = giorno + 1 END IF ultimo WRITE (*,*) giorno, '/', mese, '/', anno STOP END PROGRAM data_successiva 18 Istruzioni di Ciclo • Permettono di ripetere un insieme di istruzioni finchè una certa condizione si verifica. • Cicli indefiniti: Il numero di ripetizioni non è noto in anticipo • Cicli definiti o iterativi: Il numero di ripetizioni è noto prima dell’inizio del ciclo. 19 Cicli indefiniti: Ciclo WHILE DO istruzione 1 IF (espressione logica) EXIT istruzione 2 END DO • Quando la condizione di fine ciclo è vera, il controllo passa all’istruzione successiva a END DO. • istruzione 1 viene eseguita almeno una volta. 20 Calcolo della lunghezza di una sequenza di interi • Calcola la lunghezza di una sequenza di interi positivi terminati da uno 0 • Gli interi sono letti in input uno ad uno finchè l’utente non indica lo 0 21 Calcolo della lunghezza di una sequenza di interi (cont.) ! File: lung.for ! Scopo: primo esempio di uso di un ciclo di iterazione indefinita PROGRAM calcola_lunghezza IMPLICIT NONE INTEGER :: lunghezza !la lunghezza della sequenza INTEGER :: dato ! il dato letto in input WRITE(*,*) 'Inserisci una sequenza di interi, terminata da 0: ' lunghezza = 0 ! all'inizio la lunghezza e' inizializzata a 0 DO ! iterazione indefinita READ (*,*) dato IF (dato == 0) EXIT ! condizione di uscita dal ciclo lunghezza = lunghezza + 1 END DO WRITE(*,*) 'La sequenza (senza lo 0 finale) e'' lunga ',lunghezza STOP END PROGRAM calcola_lunghezza 22 Calcolo del Massimo Comun Divisore ! File: mcd1.for PROGRAM massimo_comun_divisore ! Questo programma legge due numeri interi a, b positivi e ne calcola ! il massimo comun divisore. ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER :: a, b ! dati letti da tastiera INTEGER :: mcd ! massimo comun divisore LOGICAL :: trovato ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Inserisci due interi positivi: ' READ (*,*) a, b IF (a <= b) THEN mcd = a ELSE mcd = b END IF trovato = .FALSE. 23 Calcolo del Massimo Comun Divisore (cont.) DO IF (mcd == 1 .OR. trovato) EXIT IF (MOD(a,mcd) == 0 .AND. MOD(b,mcd) == 0) THEN trovato = .TRUE. ELSE mcd = mcd - 1 END IF END DO WRITE (*,*) 'Massimo comun divisore di ', a, ' e ', b, ' : ', mcd STOP END PROGRAM massimo_comun_divisore 24 Calcolo della Media e della Varianza • n numeri reali x1,…., xn. 1 n • Media: X x j n j 1 2 n 2 n x j x j j 1 j 1 • Varianza: n n(n 1) 25 Calcolo della Media e della Varianza (cont.) ! File: stat.for PROGRAM media_varianza ! Questo programma calcola la media e la varianza di un insieme di ! dati positivi o nulli forniti in input ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER :: n=0 ! Numero di dati letti in input REAL :: std_dev = 0 ! Deviazione standard REAL :: sum_x = 0 ! Somma dei dati REAL :: sum_x2 = 0 ! Somma dei quadrati dei dati REAL :: x ! Dato in input REAL :: x_bar ! Media dei dati 26 Calcolo della Media e della Varianza (cont.) ! *** SEZIONE ESECUTIVA *** ! DO WRITE (*,*) 'Digita il numero: (num<0 per uscire) ' READ (*,*) x WRITE (*,*) 'Il numero e'':', x IF (x < 0) EXIT ! Calcola le Somme n = n + 1 sum_x = sum_x + x sum_x2 = sum_x2 + x**2 END DO 27 Calcolo della Media e della Varianza (cont.) ! Controlla che i dati di input siano sufficienti IF (n < 2) THEN WRITE (*,*) 'Bisogna immettere almeno due valori.' ELSE x_bar = sum_x / real(n) std_dev = sqrt ((real(n) * sum_x2 - sum_x**2) / (real(n) * real(n-1))) WRITE (*,*) 'La media di questo insieme e'':', x_bar WRITE (*,*) 'La deviazione standard e'':', std_dev WRITE (*,*) 'Il numero dei dati in input e'':', n END IF STOP END PROGRAM media_varianza 28 Cicli Annidati • All’interno di un’istruzione di ciclo si possono eseguire altre istruzioni di ciclo • E’ possibile associare un nome ad un ciclo: nome: DO ….. IF (espressione logica ) EXIT nome ….. END DO nome 29 Numeri perfetti • Un numero perfetto è un numero somma di tutti i suoi divisori ad esclusione del numero stesso. Es: 6 = 1 + 2 + 3 • Per ogni intero positivo in input viene verificato se il numero è perfetto • Il ciclo DO esterno legge i dati in input, il ciclo DO interno verifica se il numero è perfetto. 30 Numeri Perfetti (cont.) ! File: perfetto.for PROGRAM perfetto ! Questo programma determina se ogni intero positivo letto in input è ! perfetto ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER :: dato ! dato in input INTEGER :: somma = 1 ! somma dei divisori INTEGER :: i = 2 ! potenziale divisore; si parte da 2 ! *** SEZIONE ESECUTIVA *** ! !leggi: DO WRITE (*,*) 'Inserisci valore (val <= 0 per uscire): ' READ (*,*) dato IF (dato <= 0) EXIT leggi WRITE(*,*) 'Divisori di', dato, ' (oltre a 1):' 31 Numeri Perfetti (cont.) verifica: DO IF (MOD(dato,i) == 0) THEN IF (dato == i*i) THEN WRITE (*,*) i somma = somma + i ELSE WRITE (*,*) i, dato / i somma = somma + i + dato / i END IF END IF i = i + 1 IF (i*i > dato) EXIT verifica END DO verifica IF (somma == dato) THEN WRITE (*,*) dato, ' E'' UN NUMERO PERFETTO' ELSE WRITE (*,*) dato, ' non e'' un numero perfetto' END IF END DO leggi STOP END PROGRAM perfetto 32 Cicli definiti: Ciclo DO • Il numero di iterazioni è noto prima dell’esecuzione dell’istruzione di ciclo DO indice = inizio, fine, incremento istruzione 1 ……. istruzione 2 END DO 33 Ciclo DO (cont.) • inizio, fine, incremento: sono espressioni calcolate prima dell’inizio del ciclo • All’inizio: indice = inizio • Le istruzioni del corpo del ciclo sono eseguite se: abs(indice) <= abs(fine) • Dopo l’esecuzione delle istruzioni del ciclo: indice = indice + incremento 34 Ciclo DO (Cont.) • DO i = 1, 10, 2 istruzione 1 istruzione n END DO Il corpo del ciclo eseguito 5 volte • DO i = 3, -3, -2 istruzione 1 istruzione n END DO Il corpo del ciclo eseguito 4 volte 35 Calcolo del Fattoriale ! File: fatt.for ! Scopo del programma è illustrare l’uso di cicli definiti PROGRAM fatt ! Calcola il fattoriale di un intero IMPLICIT NONE INTEGER :: n, i , fattoriale ! Variabili che indicano l’intero, l’indice del ciclo ed il fattoriale WRITE (*,*) 'Inserisci un intero: ' READ (*,*) n fattoriale = 1 DO i=2, n fattoriale = fattoriale * i END DO WRITE (*,*) 'Il fattoriale di', n, ' e'':', fattoriale STOP END PROGRAM fatt 36 Stampa di un Quadrato ! File: quadrato.for ! Scopo: illustrazione di un esercizio con cicli e stringhe PROGRAM quadrato ! Questo programma legge un numero intero positivo n da tastiera e ! stampa un quadrato di asterischi di dimensione n ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER, PARAMETER :: max_lunghezza = 25 ! lunghezza massima del lato INTEGER :: n ! dato letto da tastiera INTEGER :: i ! indice dei cicli CHARACTER(max_lunghezza) :: linea ! linea da stampare 37 Stampa di un Quadrato (cont.) ! *** SEZIONE ESECUTIVA *** ! WRITE (*,*) 'Dimensione del lato (lmin=1, lmax=25): ' READ (*,*) n IF (n < 1 .OR. n > 25) THEN WRITE (*,*) n, ' e'' un input non valido.' ELSE DO i = 1, n linea(i:i) = '*' END DO DO i = n+1, max_lunghezza linea(i:i) = ' ' END DO DO i = 1, n WRITE (*,*) linea END DO END IF STOP END PROGRAM quadrato 38 Cicli DO annidati: Calcolo della Tavola Pitagorica ! File: tavolpit.for ! Scopo: illustrare un programma con cicli annidati PROGRAM tavola_pitagorica ! Questo programma legge un numero intero positivo n da tastiera e ! stampa tutti i prodotti i * j (1 <= i,j <= n), uno per riga IMPLICIT NONE INTEGER :: n INTEGER :: i,j ! il dato letto da tastiera ! indici dei cicli WRITE (*,*) 'Inserisci un intero positivo: ' READ (*,*) n WRITE (*,*) 'Tavola pitagorica da 1 a ', n, ': ' esterno: DO i = 1, n interno: DO j = 1, n WRITE (*,*) i, ' * ', j, ' = ', i*j END DO interno END DO esterno STOP END PROGRAM tavola_pitagorica 39 Traiettoria di un proiettile • Traiettoria parabolica di un proiettile sparato con velocità iniziale v0 e angolo theta dalla posizione (0,0) • vx = v0 * COS(theta) vy = v0 * SIN(theta) • Altezza dal suolo al tempo t: y(t) = vy * t + 1/2 * g * t**2 • Distanza orizzontale percorsa al tempo t x(t) = vx * t • Data la velocità v0, determinare: – la gittata (distanza orizzontale del proiettile prima di toccare terra) al variare di theta tra 0° e 90° con step di 1°. – l’angolo theta per cui la gittata è massima. 40 Calcolo della gittata • Tempo di atterraggio: vy * t + 1/2 * g * t**2 = 0 t1 = 0, t2 = - 2 * vy / g • range = vx t2 = - 2 * vx * vy / g = - 2 v0**2 * COS(theta) * SIN(theta) /g 41 Traiettoria di un proiettile (cont.) ! File: gittata.for PROGRAM gittata ! Scopo: Calcolare la distanza percorsa da un proiettile sparato con ! angolo theta e velocità v = 20 m/s ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE REAL, PARAMETER :: gradi_a_rad = 0.01745329 ! Conversione da gradi a radianti REAL, PARAMETER :: gravity = -9.81 INTEGER :: max_degrees ! Angolo di massima gittata REAL :: max_range ! Massima gittata alla velocita’ v0 REAL :: range ! Gittata con un dato angolo REAL :: radian ! Angolo iniziale in radianti INTEGER :: theta ! Angolo iniziale in gradi REAL :: v0 ! Velocita’ del proiettile 42 Traiettoria di un proiettile (cont.) ! *** SEZIONE ESECUTIVA *** ! max_range = 0. max_degrees = 0 v0 = 20. loop: DO theta = 0, 90 radian = real(theta) * gradi_a_rad range = - 2. * v0**2 * COS(radian) * SIN(radian) / gravity WRITE (*,*) 'THETA =', theta, ' gradi; Gittata =', range, ' metri' IF (range > max_range) THEN max_range = range max_degrees = theta END IF END DO loop WRITE (*,*) 'Gittata massima = ', max_range, ' a', max_degrees, ' gradi' STOP END PROGRAM gittata 43 Esercizi • Scrivere un programma che calcoli il massimo di una sequenza di interi positivi dati in input e terminati da uno 0. • Scrivere un programma che dato in input un intero n stampi un triangolo equilatero di asterischi. Ad esempio per n=5: * ** *** **** ***** • Disegnare la traiettoria di un proiettile sul piano cartesiano 44