Università degli Studi di Cagliari Corso di Laurea Magistrale in Ingegneria per l’Ambiente ed il Territorio LABORATORIO di INFORMATICA A.A. 2010/2011 Prof. Giorgio Giacinto CODIFICA DEGLI ALGORITMI IN UN LINGUAGGIO DI ALTO LIVELLO http://www.diee.unica.it/giacinto/Lab Obiettivi ! L’obiettivo di questa sezione non è quello di illustrare tutte le particolarità del linguaggio C ! In questa sezione si vuole mostrare come, dato un problema, si possa formulare un algoritmo che lo risolva. ! Gli algoritmi verranno espressi usando solo una piccola parte del linguaggio C Giorgio Giacinto 2010 Laboratorio di Informatica 2 Introduzione ! Come abbiamo visto, un linguaggio per la descrizione di algoritmi deve essere preciso e sintetico. ! ! ! La precisione è requisito essenziale per l’esecuzione automatica La sinteticità è necessaria per la comprensibilità umana del programma Per soddisfare queste due esigenze contrastanti vengono progettati linguaggi diversi ! ! per il livello macchina per il livello uomo (“alto livello”) Giorgio Giacinto 2010 Laboratorio di Informatica 3 Caratteristiche essenziali di un linguaggio di alto livello ! In un linguaggio di alto livello ! ! ! i riferimenti a elementi del programma come celle di memoria, istruzioni, costanti, ecc. sono effettuati con variabili simboliche le istruzioni e il controllo della sequenza vengono espresse in un linguaggio molto vicino al linguaggio naturale (inglese) Le variabili simboliche prendono il nome di identificatori: il nome usato per indicarle deve essere semplice da comprendere. ! Chi legge un programma scritto da altri deve poter comprendere quali operazioni vengono compiute e su quali operandi Giorgio Giacinto 2010 Laboratorio di Informatica 4 Macchina virtuale che esegue programmi in linguaggio C Bus di sistema x a Standard input alfa Pippo Standard output Unità centrale Memoria centrale Giorgio Giacinto 2010 Laboratorio di Informatica 5 Nucleo del linguaggio C ! Lo standard input, standard output e la memoria sono suddivisi in celle elementari. Ciascuna cella contiene un dato ! ! ! NOTA: dati diversi (numeri interi, reali, caratteri) richiedono celle di dimensione diversa Chiamiamo stringa una successione finita di caratteri memorizzati in celle consecutive (un carattere per cella) Per ora ipotizziamo che la dimensione della memoria e dei supporti ingresso/uscita sia illimitata. Giorgio Giacinto 2010 Laboratorio di Informatica 6 Nucleo del linguaggio C (cont.) ! Le celle di memoria sono chiamate variabili ! ! Il contenuto può essere modificato durante l’esecuzione del programma Identificatori simbolici: una successione di lettere e cifre ! ! Al primo posto sempre una lettera Distinzione maiuscole e minuscole (Var è diverso da VAR) Esempi: x, alfa, Giuseppe, DopoDomani,... Non si può usare lo stesso id. per indicare diversi elementi né usare diversi id. per lo stesso elemento Giorgio Giacinto 2010 Laboratorio di Informatica 7 Identificatori riservati (o predefiniti) ! Alcune parole sono associate a priori a qualche elemento del linguaggio ! ! ! Hanno un significato fissato a priori che non può essere modificato dal programmatore Esempio: scanf e printf indicano operazioni elementari di ingresso/uscita e non possono essere usate per indicare variabili Vengono spesso indicate col nome di parole chiave Negli editor a corredo dei compilatori, spesso le parole chiave vengono evidenziate con colori diversi rispetto agli altri elementi di un programma Giorgio Giacinto 2010 Laboratorio di Informatica 8 Struttura base di un programma C main() { ... } ! Intestazione Qui vengono inserite le istruzioni, cioè frasi in linguaggio C. Ciascuna istruzione termina con ; Il corpo del programma, cioè la sequenza di istruzioni che realizza una determinata funzione, è racchiuso fra parentesi graffe Giorgio Giacinto 2010 Laboratorio di Informatica 9 Istruzioni in linguaggio C Tre tipi di istruzioni assegnamento: associare un valore ad una variabile ingresso e uscita: servono per leggere e scrivere rispettivamente sui dispositivi di ingresso e uscita istruzioni composte: gli effetti dell’istruzione dipendono dalla verità o falsità di una espressione booleana (o condizione) Giorgio Giacinto 2010 Laboratorio di Informatica 10 Istruzioni di assegnamento Sintassi: <identificatore> = <espressione> All’identificatore viene associato il valore dell’espressione <espressione> può essere un valore costante, espressioni aritmetiche, ecc. Esempi: x = 23; w = ‘a’; y = z; alfa = x+y; r3 = (alfa*43-xgg)*(delta-32*ijj); Giorgio Giacinto 2010 Laboratorio di Informatica 11 Istruzioni di assegnamento (cont.) ! L’esecuzione di una istruzione di assegnamento comporta la valutazione dell’espressione a destra del segno = ! Agli identificatori simbolici vengono sostituiti i valori nelle celle corrispondenti al momento della valutazione Esempio: Se la cella a contiene il valore 45 e z contiene il valore 5, x = (a–z)/10; fa sì che nella cella x venga memorizzato il valore 4 Giorgio Giacinto 2010 Laboratorio di Informatica 12 Istruzioni di ingresso e uscita ! ! scanf() legge dal dispositivo standard di ingresso (stdin)un valore e lo memorizza in una variabile printf() scrive sul dispositivo standard di uscita (stdout) ! ! stdin: di solito tastiera stdout: di solito il monitor Giorgio Giacinto 2010 Laboratorio di Informatica 13 Struttura dei programmi C /* Somma sequenze di numeri */ #include <stdio.h> Direttive al pre-processore C main() { Dichiarazioni di costanti e di int numero, somma; variabili somma = 0; scanf(“%d”,&numero); while(numero!=0) { somma = somma+ numero; Istruzioni di I/O scanf(“%d”,&numero); } printf(“La somma è: %d\n”,somma); } Giorgio Giacinto 2010 Laboratorio di Informatica 14 La parte dichiarativa dei programmi ! Il linguaggio C chiede che tutte gli identificatori usati all’interno del programma vengano dichiarati ! ! ! Facilita l’individuazione di errori (ad esempio si scrive alba anziché alfa, dove alfa è stata dichiarata, mentre alba no) Notifica al C che tipo di valori dovrà memorizzare (caratteri, numeri interi, numeri in virgola mobile, ecc.) La parte dichiarativa precede la parte esecutiva che contiene le istruzioni. Giorgio Giacinto 2010 Laboratorio di Informatica 15 Dichiarazione di variabili ! Sintassi <identificatore_di_tipo> <lista_dichiarazione> <identificatore_di_tipo>::=int | float | char… <lista_dichiarazioni>::= <dichiarazione>[{,<dichiarazione>}]; <dichiarazione>::= <identificatore> | <identificatore> = <valore_iniziale> tipo: l’insieme dei valori che la variabile può assumere int: interi; float: virgola mobile; char: carattere, ecc. Giorgio Giacinto 2010 Laboratorio di Informatica 16 Dichiarazione di variabili (cont.) float int char x,y; i,j; simb; Significato: Nel programma si useranno le variabili x e y come numeri in virgola mobile, i e j come interi e simb come carattere Ne consegue che, ad es., j non potrà mai assumere il valore 3.14 (qual è il risultato di j=3.14;?) Giorgio Giacinto 2010 Laboratorio di Informatica 17 Dichiarazione di costanti Sintassi const <identificatore_di_tipo> <lista_dichiarazione> <identificatore_di_tipo>::=int | float | char… <lista_dichiarazioni>::= <dichiarazione>[{,<dichiarazione>}]; <dichiarazione>::= <identificatore> = <valore_iniziale> Una dichiarazione di costante associa in maniera permanente un valore ad un identificatore per la durata dell’esecuzione del programma Giorgio Giacinto 2010 Laboratorio di Informatica 18 Dichiarazione di costanti (cont.) const const const const float float int char PiGreco = 3.14; PiGreco = 3.1415, e = 2.718; N = 100, M = 1000; Car1 = ‘G’, Car2 = ‘R’; La definizione di costanti è utile ! ! Per utilizzare un identificatore simbolico nel corpo del programma (ad es. PiGreco al posto di 3.14) che ne migliora la comprensibilità Per poter parametrizzare il programma. Se si desidera cambiare il valore di una costante non è necessario rintracciarne tutte le occorrenze nel programma, ma è sufficiente modificare la dichiarazione iniziale. Giorgio Giacinto 2010 Laboratorio di Informatica 19 Sintassi di scanf scanf(stringa_di_controllo, elementi_da_leggere); ! La stringa_di_controllo contiene una lista di caratteri di conversione o di formato preceduti dal simbolo % (la lista è racchiusa fra “ “) In questo modo di specifica il formato con cui devono essere interpretati i caratteri letti da tastiera ! ! ! ! ! %d per leggere un intero %c per leggere un carattere %f per leggere un numero reale (floating point) %s per leggere una stringa di caratteri La lista di elementi_da_leggere contiene i nomi preceduti da & delle variabili in cui devono essere memorizzati i dati letti da tastiera (gli elementi sono separati da virgole). Le variabili sono nello stesso ordine degli elementi da leggere specificati dalla stringa_di_controllo. Giorgio Giacinto 2010 Laboratorio di Informatica 20 Esempio di utilizzo di scanf scanf(“%c%c%c%d%f”,&c1,&c2,&c3,&i,&x); Se al momento dell’esecuzione l’utente inserisce ABC 3 7.345 c1 conterrà A (c1 deve essere definita di tipo char) c2 conterrà B (c2 deve essere definita di tipo char) c3 conterrà C (c3 deve essere definita di tipo char) i conterrà 3 (i deve essere definita di tipo int) x conterrà 7.345 (x deve essere definita di tipo float) Giorgio Giacinto 2010 Laboratorio di Informatica 21 Sintassi di printf ! ! E’ la funzione che consente di generare un output formattato sul dispositivo di uscita standard printf(stringa_di_controllo, elementi_da_stampare) ! La stringa_di_controllo è una stringa (racchiusa fra “ ”) che viene stampata in uscita e che può contenere caratteri di conversione o di formato preceduti dal simbolo % e altri simboli (ad es., \n provoca un salto a nuova riga) ! %d per stampare un intero ! %c per stampare un carattere ! %f per stampare un numero reale (floating point) ! %s per stampare una stringa di caratteri Giorgio Giacinto 2010 Laboratorio di Informatica 22 Sintassi di printf (cont.) ! printf(stringa_di_controllo, elementi_da_stampare) ! ! Gli elementi_da_stampare sono costituiti da una lista di ! variabili, costanti, espressioni (gli elementi sono separati da virgola), nello stesso ordine in cui compaiono i corrispondenti caratteri di conversione nella stringa_di_controllo. I caratteri preceduti da % vengono detti di conversione perché devono convertire il contenuto delle variabili, costanti ecc. in caratteri stampabili Giorgio Giacinto 2010 Laboratorio di Informatica 23 Esempio di utilizzo di printf printf(“Lo stipendio annuo dei dipendenti di categoria %d è pari a %f Euro\n”,cat,stip); dove cat è definita come variabile intera (int) e stip come variabile reale (float). Se cat contiene il valore 6 e stip il valore 1570.58, l’istruzione stampa la stringa seguente Lo stipendio annuo dei dipendenti di categoria 6 è pari a 1570.5 Euro e il cursore viene spostato sulla riga seguente Giorgio Giacinto 2010 Laboratorio di Informatica 24 Esempio di utilizzo di printf (cont.) printf(%s\n%c%c\n\n%s\n,“Questo programma è stato scritto da”,iniz-nome,iniz-cognome,”Buon lavoro!”); Se iniz-nome e iniz-cognome sono definite come variabile carattere (char) e contengono rispettivamente M e P l’istruzione stampa la stringa seguente: Questo programma è stato scritto da MP Buon lavoro! e il cursore viene spostato sulla riga seguente Giorgio Giacinto 2010 Laboratorio di Informatica 25 Il preprocessore C ! ! ! Costituisce la prima fase della compilazione di un programma in linguaggio C La direttiva #include viene usata per includere nel programma corrente il contenuto del file specificato. La direttiva #define viene usata per sostituire ad un identificatore una stringa arbitraria di caratteri ! Ad es. #define DIMENSIONE 100 ad ogni occorrenza di DIMENSIONE il preprocessore sostituisce il valore 100 ! A differenza di una costante, non è una variabile in memoria, ma la sostituzione viene effettuata dal compilatore prima della compilazione vera e propria Giorgio Giacinto 2010 Laboratorio di Informatica 26 #include ! E’ comodo disporre di un certo insieme di funzioni e definizioni di libreria. ! ! Sono funzioni e definizioni che estendono le funzionalità di base del linguaggio C Le funzioni di libreria possono essere definite dall’utente oppure appartenere a un insieme definito dallo standard ANSI C ! Le funzioni della libreria standard sono disponibili in qualunque ambiente di programmazione e hanno sempre la stessa sintassi Giorgio Giacinto 2010 Laboratorio di Informatica 27 #include <stdio.h> ! ! ! Il linguaggio C in senso stretto non possiede istruzioni per realizzare I/O In ciascun ambiente di programmazione sono sempre disponibili le funzioni scanf e printf Le funzioni per l’I/O sono sempre definite nel file stdio.h ! #include <stdio.h> produce come effetto l’inclusione nel programma corrente del file stdio.h. ed è necessario per usare le funzioni di I/O (come ad es. printf e scanf) Le parentesi angolate <> indicano che il file si trova nella directory predefinita dal compilatore che contiene le libreria standard. Giorgio Giacinto 2010 Laboratorio di Informatica 28 Istruzioni composte ! Sono costruite componendo istruzioni più semplici ! Questa caratteristica non è posseduta dalla macchina di Von Neumann ! La costruzioni di istruzioni composte non ha limiti: ogni istruzione composta può contenere al suo interno istruzioni composte Giorgio Giacinto 2010 Laboratorio di Informatica 29 Istruzioni composte (cont.) ! Sono istruzioni che producono effetti diversi a seconda che siano verificate o meno certe condizioni sul valore delle variabili ! Le condizioni sono espressioni booleane il cui valore può essere solo vero o falso ! Le condizioni sono costruite mediante operatori relazionali e operatori logici Giorgio Giacinto 2010 Laboratorio di Informatica 30 Operatori relazionali e logici Operatori relazionali == != < > <= >= uguale diverso minore maggiore minore o uguale maggiore o uguale Giorgio Giacinto 2010 Operatori logici && || ! AND OR NOT N.B. nel linguaggio C il valore logico vero corrisponde a qualunque valore diverso da 0 mentre falso corrisponde al valore 0 Laboratorio di Informatica 31 Esempi espressioni condizionali x == 0 (vero se il valore memorizzato in x è 0) alfa > beta && x != 3 (vero se il valore memorizzato in alfa è maggiore del valore memorizzato in beta e se contemporaneamente il valore memorizzato in x è diverso da 3) !((a + b) * 3 > x || a < c) Si valutano le espressioni (a + b) * 3 > x e a < c. Se almeno una delle due è vera, o se sono entrambe vere (OR logico) allora il risultato è falso (tutta l’espressioni è negata) Giorgio Giacinto 2010 Laboratorio di Informatica 32 Precedenza operatori Giorgio Giacinto 2010 Laboratorio di Informatica 33 Istruzione condizionale Sintassi: <istruzione condizionale>::= if(<espressione condizionale>) <sequenza istruzioni> [else <sequenza istruzioni>] <sequenza istruzioni>::=<istruzione>|{{<istruzione>}2+} ! Se l’espressione condizionale è vera, viene eseguita la sequenza di istruzioni che segue if() ! E’ opzionale inserire una sequenza di istruzioni da eseguire se l’espressione condizionale è falsa Giorgio Giacinto 2010 Laboratorio di Informatica 34 Esempi istruzione condizionale if(x == 0) z = 5; else y = z + w*y; se x vale 0, allora assegna 5 a z altrimenti assegna a y il valore di z+w*y if((x+y)*(z-2)>(23+v)) {z=x+1; y=13+x;} if((x==y && z>3) || w!=y) z=5; else{y=z+w*y; x=z;} Le espressioni seguenti sono scorrette (perché?) if(x==0) else y=z; y=34; if(x==0) a; else b+c; Giorgio Giacinto 2010 Laboratorio di Informatica 35 Istruzione iterativa (ciclo o loop) Sintassi: <istruzione iterativa>::= while(<espressione condizionale>) <sequenza istruzioni> <sequenza istruzioni>::=<istruzione>|{{<istruzione>}2+} ! Si esegue ripetutamente la sequenza di istruzioni fintantoché l’espressione condizionale è vera ! Si valuta l’espressione condizionale. Se è falsa, il programma prosegue senza eseguire la sequenza di istruzioni. Se è vera, si esegue la sequenza di istruzioni e poi si prosegue ciclicamente valutando la condizione. Il ciclo termina quando la condizione è falsa. Giorgio Giacinto 2010 Laboratorio di Informatica 36 Esempi di istruzioni iterative while(x >= 0) x = x-1; decrementa x fino a che x è maggiore o uguale a 0. Il ciclo termina quando x assume il valore –1 while(z != y) {y = z-x; x = x*3;} In dipendenza dai valori iniziali di x, y e z questo ciclo potrebbe essere infinito Giorgio Giacinto 2010 Laboratorio di Informatica 37 Primi esempi di programmi in C ! Vedremo esempi di complessità via via cresecente ! Per aiutare la lettura e la comprensione di un programma ! ! Lettura: le istruzioni vengono indentate. La sequenza di istruzioni che dipende da espressioni condizionali viene scritta con un rientro a destra rispetto all’allineamento della istruzione condizionale Comprensione: inserimento di commenti in linguaggio naturale. I commenti sono compresi fra i simboli /* e */ e sono ignorati dal compilatore Giorgio Giacinto 2010 Laboratorio di Informatica 38 Avvertenze sui primi esempi di programmi in C ! Scopo di questi esempi è illustrare il flusso delle operazioni da eseguire ! ! La sintassi completa del C non è usata per maggiore chiarezza Per compilare ed eseguire i programmi seguenti occorre completarne la scrittura ! ! ! inclusione della libreria stdio.h dichiarazione delle variabili usate completamento istruzioni I/O Giorgio Giacinto 2010 Laboratorio di Informatica 39 (1) Lettura di due numeri da stdin e stampa del maggiore /*Prima versione*/ main() { scanf(x); scanf(y); if(x>y) z=x; else z=y; printf(z); } Giorgio Giacinto 2010 /*Seconda versione*/ main() { scanf(x); scanf(y); if(x>y) printf(x); else printf(y); } Laboratorio di Informatica 40 (2) Lettura sequenza numeri e ricerca del primo 0 main() { uno=1; scanf(dato); while(dato) scanf(dato); printf(uno); } N.B. L’espressione del while equivale a dato!=0 Giorgio Giacinto 2010 Laboratorio di Informatica 41 (3) Somma di una sequenza di numeri Ipotesi: la cifra ‘0’ indica la fine della sequenza main() { somma=0; scanf(numero); while(numero) { somma = somma + numero; scanf(numero); } printf(somma); } Giorgio Giacinto 2010 Laboratorio di Informatica 42 (4) Gioco “carta, forbici, sasso” ! Il programma deve realizzare il gioco seguente fra due giocatori ! ! ! Il programma legge da stdin due caratteri che rappresentano gli oggetti scelti dai due giocatori ! ! Ogni giocatore sceglie un oggetto fra carta, forbici e sasso I due oggetti vengono confrontati secono la logica: ! la carta prevale sul sasso ! le forbici prevale sulla carta ! il sasso prevale sulle forbici ‘c’=carta, ‘f’=forbici, ‘s’=sasso Il programma scrive su stdout il vincitore o il risultato pari nel caso di scelta dello stesso colore Giorgio Giacinto 2010 Laboratorio di Informatica 43 (4) Gioco “carta, forbici, sasso” main() { scanf(PrimoOggetto); scanf(SecondoOggetto); if(PrimoOggetto == SecondoOggetto) printf(“Il gioco è pari”); else if((PrimoOggetto ==‘c’&& SecondoOggetto ==‘s’) || (PrimoOggetto ==‘f’&& SecondoOggetto ==‘c’) || (PrimoOggetto ==‘s’&& SecondoOggetto ==‘f’)) printf(“Il vincitore è il giocatore n. 1”); else printf(“Il vincitore è il giocatore n. 2”); } Giorgio Giacinto 2010 Laboratorio di Informatica 44 (4) Gioco “carta, forbici, sasso” osservazioni ! Abbiamo usato istruzioni composte annidate ! ! ! Il primo if stabilisce se c’è un vincitore o no Se c’è un vincitore, bisogna stabilire chi è (secondo if) Se in una serie di if annidati, qualcuno è seguito da else e qualcuno no, come si interpreta? il C usa la convenzione di associare l’else all’if più vicino Ad esempio: if(C1) if(C2) S1; else S2; l’else è l’alternativa a if(C2) Se invece l’else deve essere l’alternativa a if(C1) if(C1) {if(C2) S1;} else S2; ! Giorgio Giacinto 2010 Laboratorio di Informatica 45 (5) Triangoli Problema: Dati tre numeri in ingresso, stabilire se si può trattare delle lunghezze dei tre lati di un triangolo Proprietà dei lati di un triangolo: ciascun lato ha lunghezza inferiore della somma degli altri due Se si tratta delle lunghezze dei tre lati di un triangolo, determinare se è scaleno, isoscele o equilatero. Giorgio Giacinto 2010 Laboratorio di Informatica 46 (5) Triangoli - listato C main() { scanf(X); scanf(Y); scanf(Z); if((X<Y+Z)&&(Y<X+Z)&&(Z<X+Y)) if(X == Y && Y == Z) printf(“I dati letti corrispondono a un triangolo equilatero”); else if(X == Y || Y == Z || X == Z) printf(“I dati letti corrispondono a un triangolo isoscele”); else printf(“I dati letti corrispondono a un triangolo scaleno”); else printf(“I dati letti non corrispondono a nessun triangolo”); } Giorgio Giacinto 2010 Laboratorio di Informatica 47 (5) Triangoli - osservazioni ! ! Per determinare il tipo di triangolo potevano essere scelte altre strade (ad es. prima la verifica se isoscele o equilatero, altrimenti scaleno) Nota sulle espressioni condizionali: In analisi matematica a==b==c oppure a<b<c sono espressioni lecite, MA NON IN C a==b==c verrebbe eseguita da sn verso dx. a==b restituisce un valore booleano (attenzione! In C falso è rappresentato dallo 0, vero da valori diversi da 0)… e non ha senso confrontarlo con c! Giorgio Giacinto 2010 Laboratorio di Informatica 48 (6) Massimo comun divisore Primo algoritmo Dati due numeri interi positivi m e n: ! fai la scansione di tutti i numeri compresi fra 1 e il minimo fra m e n ! Per ciascuno di essi stabilisci se è un divisore comune fra m e n (la divisione deve dare resto 0) ! Se sì, memorizza come MCD attuale ! Considera l’intero successivo. ! Alla fine, la variabile usata per memorizzare il MCD temporaneo conterrà il MCD fra i due numeri Giorgio Giacinto 2010 Laboratorio di Informatica 49 (6) Massimo comun divisore Primo algoritmo - listato C main() { scanf(n); scanf(m); MCD = 1; if(n <= m) min = n; else min = m; contatore = 1; while (contatore <= min) { if(n % contatore == 0 && m % contatore == 0) MCD = contatore; contatore = contatore + 1; } printf(MCD); } Giorgio Giacinto 2010 Laboratorio di Informatica 50 (6) Massimo comun divisore Algoritmo di Euclide Se m = n allora MCD(m,n) = m = n ! Se m ! n (ad es. m > n) allora MCD(m,n) = MCD(m-n,n) Infatti se k è un divisore comune a m e a n, ! m = k!d e n = k!r ! m - n = k ! (d - r) ! d – r è un intero positivo ! Simmetricamente se k è un divisore comune a m-n e n, allora lo è anche per m e n ! Si ottiene una catena di uguaglianze fra MCD che termina quando m e n sono uguali (vedi prima riga), magari uguali al valore 1. ! Giorgio Giacinto 2010 Laboratorio di Informatica 51 (6) Massimo comun divisore Algoritmo di Euclide - listato C main() { scanf(n); scanf(m); while(m != n) if(m > n) m = m – n; else /* sicuramente n > m perché il ciclo è per m != n */ n = n - m; MCD = n; printf(MCD); } Giorgio Giacinto 2010 Laboratorio di Informatica 52 (6) Massimo comun divisore commenti sui due algoritmi ! Il secondo algoritmo è più elegante (è vicino a una formulazione ricorsiva. Qual è?) ! Il primo algoritmo è più efficiente se la differenza fra i due numeri è grande, altrimenti è più efficiente il secondo ! Il numero di calcoli da effettuare nel primo algoritmo dipende dalla dimensione del numero più piccolo, mentre nel secondo dipende dalla differenza dei due numeri. Giorgio Giacinto 2010 Laboratorio di Informatica 53 Costruzione incrementale di programmi ! ! La soluzione di problemi complessi richiede spesso la costruzione di algoritmi complessi Una tecnica per progettare algoritmi complessi consiste nell’affrontare il problema a diversi livelli di dettaglio ! ! Inizialmente si producono formulazione compatte ! Ad esempio, se è necessario effettuare un ordinamento, non si precisa l’algoritmo di ordinamento Le formulazioni compatte di un algoritmo sono spesso espresse usando uno pseudocodice, cioè un ibrido fra un linguaggio di programmazione e il linguaggio naturale Giorgio Giacinto 2010 Laboratorio di Informatica 54