Esempio: Leggere due interi positivi e calcolarne il massimo comun divisore. MCD(12, 8) = 4 MCD(12, 6) = 6 MCD(12, 7) = 1 Sfruttando direttamente la definizione di MCD osservazione: 1 MCD(m,n) min(m,n) = si provano i numeri compresi tra 1 e min(m,n) conviene iniziare da min(m,n) e scendere verso 1 E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 1
Algoritmo: Calcola MCD di due interi positivi m ed n inizializza mcd al minimo tra m ed n while mcd > 1 e non si e trovato un divisore comune { if mcd divide sia m che n si e trovato un divisore comune else decrementa mcd di 1 } Il valore di mcd è il MCD cercato Osservazioni il ciclo termina sempre perché ad ogni iterazione o si è trovato un divisore o si decrementa mcd di 1 (al più si arriva a 1) per verificare se si è trovato il MCD si utilizza una variabile booleana (nella guardia del ciclo) Implementazione in JavaScript... E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 2
function mcd(m, n){ /* i due numeri letti */ var mm; /* il massimo comun divisore */ var trovato = false; /* var. booleana: inizialmente false */ if (m <= n) /*inizializza mcd al minimo tra m e n*/ mm = m; else mm = n; while (mm > 1 &&!trovato) if ((m % mm == 0) && (n % mm == 0)) /* mcd divide entrambi */ trovato = true; else mm = mm -1; return (mm);} E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 3
Quante volte viene eseguito il ciclo? caso migliore: 1 volta (quando m divide n o viceversa) es. MCD(500, 1000) caso peggiore: min(m,n) volte (quando MCD(m,n)=1) es. MCD(500, 1001) l algoritmo si comporta male se m e n sono grandi e MCD(m,n) è piccolo E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 4
Metodo di Euclide per il calcolo del MCD Permette di ridursi più velocemente a numeri più piccoli, sfruttando le seguenti proprietà: MCD(x, x) = x MCD(x, y) = MCD(x-y, y) se x>y MCD(x, y) = MCD(x, y-x) se y>x I divisori comuni di m ed n, con m>n, sono anche divisori di m-n. Es.: MCD(12, 8) = MCD(12-8, 8) = MCD(4, 8-4) = 4 Come si ottiene un algoritmo? Si applica ripetutamente il procedimento fino a che non si ottiene che m=n. m n maggiore - minore 210 63 147 147 63 84 Esempio: 84 63 21 21 63 42 21 42 21 21 21 E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 5
Algoritmo: di Euclide per il calcolo del MCD function mcd (m,n){ while (m!= n) if (m > n) m = m - n; else n = n - m; return (m); } Cosa succede se m=n=0? = il risultato è 0 E se m=0 e n 0 (o viceversa)? = si entra in un ciclo infinito E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 6
Controllo dei valori Tipico problema che bisogna risolvere in JavaScript per controllare i dati inseriti in una pagina Web. var m, n; function intpositivo (){ var m=asknum(); while (m <= 0) m=asknum(); return (m); } function mcd(m){...} m=intpositivo(); n=intpsitivo(); print ("MCD di "+m+" e "+n+" e "+mcd(m,n)); Un modo più semplice di definire intpositivo, è di usare un altro costrutto. E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 7
Istruzione do-while Nell istruzione while la condizione di fine ciclo viene controllata all inizio di ogni iterazione. L istruzione do-while è simile all istruzione while, ma la condizione viene controllata alla fine di ogni iterazione Sintassi: do istruzione while (espressione); Semantica: è equivalente a istruzione while (espressione) istruzione = una iterazione viene eseguita comunque. E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 8
Esempio: Lunghezza di una sequenza di interi terminata da 0, usando do-while. } function (){ var lunghezza = 0; /* lunghezza della sequenza */ var dato; /* dato letto di volta in volta */ do { dato=asknum(); lunghezza=lunghezza+1; } while (dato!= 0); return lunghezza - 1; Nota: lo 0 finale non è conteggiato (non fa parte della sequenza, fa da terminatore) E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 9
Metodo di Euclide con i resti per il calcolo del MCD Cosa succede se m n? Esempio: MCD(1000, 2) MCD(1001, 500) 1000 2 1001 500 998 2 501 500 996 2 1 500...... 2 2 1 1 Come possiamo comprimere questa lunga sequenza di sottrazioni? Metodo di Euclide: sia m = n k + r (con 0 r< m) MCD(m, n) = n se r=0 MCD(m, n) = MCD(r, n) se r 0 E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 10
Algoritmo di Euclide con i resti per il calcolo del MCD di due interi m ed n while m ed n sono entrambi 0 { sostituisci il maggiore tra m ed n con il resto della divisione del maggiore per il minore } Il MCD è il numero tra i due che e diverso da 0 Esercizio Tradurre l algoritmo in JavaScript E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 11
Cicli annidati Il corpo di un ciclo può contenere a sua volta un ciclo. Esempio: Stampa della tavola pitagorica. Usiamo una stringa (s) per aggiungere i valori e i caratteri di formattamento in modo da ottenere la stampa su più righe allineata per colonne. Algoritmo for ogni riga tra 1 e 10 { for ogni colonna tra 1 e 10 aggiungi ad s il valore riga * colonna e il carattere per l allineamento aggiungi ad s un a capo } E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 12
Traduzione in JavaScript function pitagora(n,m){ var riga, colonna, s=""; for (riga=1; riga<=n; riga++) { for(colonna=1; colonna<=m;colonna++) s=s+riga*colonna+"\t"; s=s+"\n"; } return s; } print(pitagora(asknum(),asknum())); E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 13
Completiamo le istruzioni condizionali: Istruzione switch Può essere usata per realizzare una selezione a più vie. Sintassi: switch (espressione) { case espressione-1: istruzioni-1... case espressione-n: istruzioni-n default : istruzioni-default } Semantica: 1. viene valutata espressione ottenendo un valore v 2. vengono valutate le espressione-i in sequenza, se il valore di espressione-i è uguale a v, allora vengono eseguite le istruzioni-i 3. Se non esiste nessuna espressione il cui valore è uguale a v, allora vengono eseguite le istruzioni-default Attenzione, in questo modo vengono valutate tutte le espressioni che precedono quella (se esiste) il cui valore risulta uguale a v E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 14
Esempio: var giorno=asknum(); switch (giorno) { case 1: print("lunedi "); case 2: print("martedi "); case 3: print("mercoledi "); case 4: print("giovedi "); case 5: print("venerdi "); case 6: print("sabato"); case 7: print("domenica"); default : print("errore"); E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 15
Se abbiamo più valori a cui corrispondono le stesse istruzioni, possiamo raggrupparli come segue: case espressione-1: case espressione-2: istruzioni Esempio: var giorno=asknum(); { switch (giorno) { case 1: case 2: case 3: case 4: case 5: print("giorno feriale"); case 6: case 7: print("week end"); default : print("errore"); } E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 16
In realtà JavaScript non richiede che nei case di un istruzione switch l ultima istruzione sia break. Quindi, in generale la sintassi di un istruzione switch è: switch (espressione) { case espressione-1: istruzioni-1... case espressione-n: istruzioni-n default : istruzioni-default } Semantica: 1. viene prima valutata espressione ottenendo il valore v 2. vengono poi valutate le espressioni-i in sequenza finchè si trova un espressione il cui valore è uguale a v 3. se una tale espressione-i viene trovata, allora si eseguono in sequenza istruzioni-i, istruzioni-(i+1),..., fino a quando non si incontra break o è terminata l istruzione switch, altrimenti vengono eseguite istruzioni-default E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 17
Più case di uno switch eseguiti in sequenza (corretto) Esempio: Scrivere un programma che dato un intero k stampa i nomi dei poligoni con un numero di lati minore o uguale a k. Per problemi di spazio k 6. var poligoni=asknum();{ switch (poligoni) { case 6: print("esagono\n"); case 5: print("pentagono\n"); case 4: print("rettangolo\n"); case 3: print (triangolo\n"); case 2: case 1: print("nessuno"); default : print(" Errore\n");} N.B. Quando si omettono i break, diventa rilevante l ordine in cui vengono scritti i vari case. Questo può essere facile causa di errori. È buona norma mettere break come ultima istruzione di ogni case E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 18
Più case di uno switch eseguiti in sequenza (scorretto) var mese){ switch (mese) { case 1: case 2: case 3: print("inverno"); case 4 : case 5: case 6: print("primavera"); case 7: case 8: case 9: print("estate"); case 10: case 11: case 12: print("autunno"); default : print("mese non valido"); } Attenzione I casi in cui si utilizza un switch senza break nei case sono veramente pochi, invece è facile sbagliare e omettere i break. E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 19
Uso di return invece di break I break possono essere sostituiti da return se questo è il caso. Vediamo l esempio precedente in cui si definisce una funzione: Esempio: Calcolo della stagione dato il mese. function Stagione (mese){ switch (mese) { case 1: case 2: case 3: return ("Inverno"); case 4 : case 5: case 6: return ("Primavera"); case 7: case 8: case 9: return ("Estate"); case 10: case 11: case 12: return ("Autunno"); default : return ("Mese non valido"); } In questo caso il return funzione. fa terminare l esecuzione del corpo della E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 20
Il programma precedente è equivalente al programma seguente: } function Stagione (mese){ var s; switch (mese) { case 1: case 2: case 3: s="inverno"; case 4 : case 5: case 6: s="primavera";break case 7: case 8: case 9: s="estate";break case 10: case 11: case 12: s="autunno";break default : s="mese non valido"; } return s; E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 21
Osservazioni sul switch Notare che dopo il case compare un expressione e non una costante come negli esempi mostrati. Questa caratteristica, non presente negli altri linguaggi, tipo C e Java, non sembra molto utile. (Sconsiglio di utilizzarla) Il programma precedente potrebbe essere scritto utilizzando l if nel modo seguente: if (mese==1 mese==2 mese==3) s="inverno"; else if (mese==4 mese==5 mese==6) s="primavera"; else if (mese==7 mese==8 mese==9) s="estate"; else if (mese==10 mese==11 mese==12) s="autunno"; Posso sempre trascrivere lo switch con un if in questo modo? E. Occhiuto Fondamenti Teorici e Programmazione- 437AA pag. 22