Il metodo dei raffinamenti successivi (top-down) è una metodologia di programmazione basata sui seguenti principi:
Divide-et-impera: il problema da risolvere è scomposto in (sotto)problemi “più piccoli” che possono essere gestiti più facilmente
Ogni sottoproblema verrà successivamente risolto con una codifica diretta, oppure a esso si riapplicherà lo stessa tecnica (raffinamento)
Astrazione: il problema viene inizialmente affrontato nel suo complesso, studiandone i particolari in un secondo momento
È organizzato nelle seguenti fasi
1. Analisi del problema: capire bene il problema per convincersi che esiste una soluzione
input : di quale informazione si dispone
output: che cosa esattamente si vuole ottenere
spesso ci si convince di aver trovato una soluzione al problema ma questa risolve un problema più semplice di quello dato
2. Individuare un algoritmo (G), ossia una successione finita di azioni che risolvono il problema
azione: una serie di operazioni che quando effettuate producono un risultato previsto e ben determinato (determinismo)
si compiono in un certo intervallo di tempo (discretismo: finitezza dell’azione). Ogni azione modifica lo stato di uno o più oggetti
ci rendiamo conto che l’azione ha prodotto un risultato proprio dal cambiamento di stato dell’oggetto stesso.
istruzioni di programma (PG): comandi (in un linguaggio formale) interpretati dall’esecutore associando in modo univoco azioni
3. Verifica e raffinamento: verificare che la successione di azioni risolve veramente il problema …
… se la risposta è affermativa allora abbiamo un algoritmo che risolve il problema … per ogni azione dell’algoritmo:
… altrimenti tornare al punto 1.
4. Implementazione: traduci le azioni in istruzioni del programma
Il metodo dei raffinamenti successivi può essere così schematizzato:
Lo pseudocodice è un linguaggio artificiale e parzialmente formalizzato per esprimere le (macro) azioni di un algoritmo
Lo pseudocodice è un linguaggio artificiale e parzialmente formalizzato per esprimere le (macro)azioni di un algoritmo
Problema:
Dati un capitale iniziale C ed un tasso di interesse annuo T calcolare e stampare l’interesse maturato (I) ed il capitale risultante (CR) dopo un anno, dopo due anni e dopo tre anni.
La stampa deve essere del tipo:
2. Individuare un algoritmo:
Come partenza si individui una serie di macro azioni che risolvono il problema
3. Verifica e raffinamento:
L’algoritmo risolve il problema posto se si conoscono le formule per il calcolo dell’interesse maturato (I) e del capitale risultante (CR)
3. Verifica e raffinamento:
L’algoritmo risolve il problema posto se si conoscono le formule per il calcolo dell’interesse maturato (I) e del capitale risultante (CR)
3. Verifica e raffinamento:
L’algoritmo risolve il problema posto se si conoscono le formule per il calcolo dell’interesse maturato (I) e del capitale risultante (CR)
4. implementazione:
Ogni azione dell’algoritmo è traducibile in istruzioni del linguaggio C++
Problema: Calcolare la somma di due frazioni n1/d1, n2/d2 e ridurla ai minimi termini.
Primo raffinamento:
I quattro numeri in input non possono essere quattro interi qualsiasi perché un denominatore non può mai essere zero.
Quindi precondizioni: d1≠0 e d2≠0
Per ridurre num e den ai minimi termini dobbiamo prima trovare il massimo comun divisore k, e successivamente effettuare le operazioni num←num/k, den←den/k.
Calcolare la somma di due frazioni n1/d1, n2/d2 e ridurla ai minimi termini.
Secondo raffinamento:
leggi(n1,d1,n2,d2) (precondizione: d1≠0 e d2≠0)
den←d1*d2
num←n1*d2+n2*d1
Calcola k, massimo comun divisore di num e den
num←num/k
den←den/k
Terzo raffinamento:
leggi(n1,d1,n2,d2) (precondizione: d1>0,d2>0)
den←d1*d2
num←n1*d2+n2*d1
n=num
d=den
while d!=0
temp=n%d
n←d
d←temp
k=n
num←num/k
den←den/k
Esercizi
1. Scrivere un programma che, dato in input un intero positivo, calcola separatamente le cifre del numero e le stampa separate da uno spazio
2. Sulla base del programma precedente scrivere un programma che dato in input un intero positivo, dia come risultato il numero con le cifre in ordine inverso:
3. Due numeri interi a e b si dicono coprimi se MCD(a,b) = 1. Scrivere un programma che dati in input due numeri interi stampi a video ‘vero’ se sono coprimi, ‘falso’ altrimenti
4. Un numero si dice primo se è divisibile solo per 1 e per sé stesso. Scrivere un programma che, dato in input un numero intero positivo stampi a video ‘vero’ se è primo, ‘falso’ altrimenti
Esercizi:
1. Un commerciante, per vendere di più un suo prodotto, il cui prezzo è di 15,75 €, propone uno sconto del 12% per i clienti che ne acquistano più di 500 unità. Scrivere un programma che calcoli il ricavo effettivo per un acquisto di x unità.
2. Quali sono i cambiamenti da apportare al programma dell’esercizio precedente nel caso in cui il commerciante applichi uno sconto ulteriore del 10% quando un cliente acquisti almeno 1000 unità?
3. Scrivere un programma che chieda in input esattamente N numeri interi relativi compresi tra 100 e -100 e li stampi. Utilizzando tale programma scrivere un altro programma che stampi
Esercizi:
4. Scrivere un programma che assegnato un numero intero positivo stampi la somma dei suoi divisori ( escluso se stesso )
5. Scrivere un programma che assegnato un numero intero positivo stampi ‘vero’ se il numero è perfetto, ‘falso’ altrimenti
un numero è perfetto se e solo la somma dei suoi divisori, escluso se stesso, è uguale al numero stesso: 6=1+2+3 è perfetto 8=1+2+4 non lo è.
6. Per produrre una vernice sono necessari 10 grammi di un certo additivo per ogni chilo di prodotto fino a 10 chili e 5 grammi al chilo per i chili eccedenti. Scrivere un programma che fornisca la quantità di additivo necessaria in base al quantitativo di vernice richiesto
L’astrazione procedurale consiste nel descrivere tutti i sottoproblemi in cui un problema è descrivibile sostituendo poi a queste descrizioni una chiamata ad un sottoprogramma, non ancora scritto, il cui compito sarà quello di risolvere il corrispondente sottoproblema.
Il sottoprogramma dovrà ricevere tutta l’informazione (i dati) necessari per poter risolvere il problema.
A questo punto si scrive lo pseudo codice per ognuno dei sottoprogrammi.
Naturalmente può accadere che qualcuno dei sottoprogrammi sia ancora così complesso da richiedere a sua volta la sua scomposizione in ulteriori sottoprogrammi.
Astrazione procedurale è una tecnica di sviluppo dei programmi in forma di procedure che realizza il metodo dei raffinamenti successivi
1. Decomposizione problema:
2. Identificare dipendenze, cioè l’ordine di risoluzione dei task
3. Individuare precondizioni (postcondizioni)
4. Implementazione algoritmo
Esistono due tipi di sottoprogrammi: le procedure e le funzioni
Le funzioni restituiscono sempre un solo valore
Le procedure non restituiscono valori
In C++ esistono solo funzioni
una procedura è una funzione che ritorna il valore void
Una chiamata di funzione ha la seguente sintassi:
nome(parametri);
Esempio: k = mcd(a,b); calcola il massimo comun divisore di due numeri interi
La chiamata di una funzione non di tipo void può essere inserita come:
Se la funzione è di tipo void (procedura), la chiamata non può essere inserita in una espressione, ma deve assumere la forma di un’istruzione a se stante
Esempio:
k = (mcd(a,b) * n) / 2;
foo(mcd(a,b), d);
La definizione di funzione ha la seguente sintassi:
tipo nome (argomenti) {
istruzione1;
…
}
Dove:
La definizione di funzione ha la seguente sintassi:
tipo nome (argomenti) {
istruzione1;
…
}
Esempio:
char MiaFunz(int dato, float valore)
la funzione di nome MiaFunz riceve dal programma chiamante gli argomenti:
int
), efloat
),e ritorna un risultato di tipo char
.
Nel codice di implementazione di una funzione l’istruzione di ritorno al programma chiamante é:
return espressione;
return
; (da solo).
Definiamo una funzione per l’algoritmo (di Euclide) che calcola il MCD di due interi a e b:
Si tratta di una vera funzione perché gli argomenti sono usati solo per il calcolo del MCD
1. Prime nozioni di Programmazione
2. C++ elementi di un programma
3. Le istruzioni di I/O standard
5. C++ funzioni matematiche ed espressioni booleane
6. Le strutture di controllo - parte seconda
8. Array di caratteri e tipi astratti
9. Astrazione procedurale: Procedure e Funzioni
10. Astrazione procedurale: Procedure e Funzioni -parte seconda
11. Astrazione procedurale: Procedure e Funzioni - parte terza
12. Librerie
13. Le strutture di controllo - parte terza
14. Algoritmi
16. I File di testo
17. La classe string