Sottoprogrammi Diagrammi in MATLAB

Documenti analoghi
Diagrammi 2D e 3D Funzioni di ordine superiore

Diagrammi 2D e 3D Funzioni di ordine superiore

Diagrammi 2D e 3D Funzioni di ordine superiore

Matlab: funzioni. Daniele Loiacono, Vittorio Zaccaria

x = input('inserisci x: '); fx = 1 for ii = 1 : x fx = fx * ii; end if (fx > 220) y = input('inserisci y: '); fy = 1 for ii = 1 : y fy = fy * ii; end

x = input('inserisci x: '); fx = 1 for ii = 1 : x fx = fx * ii; end if (fx > 220) y = input('inserisci y: '); fy = 1 for ii = 1 : y fy = fy * ii; end

Sottoprogrammi. Funzioni in Matlab/Octave

Matlab: Funzioni. Informatica B. Daniele Loiacono

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOINGEGNERIA. INFORMATICA B Ingegneria Elettrica. La ricorsione

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOINGEGNERIA INFORMATICA B + C

studente = struct('nome', 'Giovanni', 'eta', 24) studente.nome = 'Giovanni'; studente.eta = 24;

RICORSIONE. Informatica B - A.A. 2013/2014

Iterazione Vs Ricorsione

Matlab: Funzioni. Informatica B AA 17/18 Luca Cassano 22 Novembre Informatica B, AA 17/18, Luca Cassano

Programmazione ricorsiva

Matlab: Script e Funzioni

Introduzione a Matlab

studente = struct('nome', 'Giovanni', 'eta', 24) studente.nome = 'Giovanni'; studente.eta = 24;

Iterazione Vs Ricorsione

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

CORSO DI LAUREA IN INGEGNERIA ELETTRICA

Matlab: introduzione

Ogni parte non cancellata a penna sarà considerata parte integrante della soluzione.

Funzioni, Stack e Visibilità delle Variabili in C

Funzioni, Stack e Visibilità delle Variabili in C

LA RICORSIONE LA RICORSIONE

Esempio: il fattoriale di un numero fact(n) = n! n!: Z! N n! vale 1 se n " 0 n! vale n*(n-1)! se n > 0. Codifica:

Introduzione al MATLAB c Parte 2

A.A. 2018/2019. Fondamenti di Programmazione in MATLAB FONDAMENTI DI INFORMATICA E PROGRAMMAZIONE. Docente Prof. Raffaele Pizzolante

Operativamente, risolvere un problema con un approccio ricorsivo comporta

Algoritmi stabili e instabili

function f = fattoriale(n) f = 1; for ii = 2 : n f = f * ii; end

LA RICORSIONE LA RICORSIONE LA RICORSIONE: ESEMPIO LA RICORSIONE: ESEMPIO LA RICORSIONE: ESEMPIO LA RICORSIONE: ESEMPIO

Variabile, costante ed espressione

La ricorsione. Induzione nel progetto e nella verifica di programmi ricorsivi. Le forme della ricorsione

Corso di Fondamenti di Programmazione canale E-O. Un esempio. Funzioni ricorsive. La ricorsione

Matlab: Variabili e Array. Informatica B

LA RICORSIONE! Una funzione matematica è definita ricorsivamente quando nella sua definizione compare un riferimento a se stessa

1. Si scriva una function Matlab che implementa il seguente metodo di punto fisso

int main(){ int numero; /* numero di cui voglio calcolare il fattoriale */ int fatt; /* memorizzo il fattoriale di numero */ int somma=0;

FUNZIONI. attribuire un nome ad un insieme di istruzioni parametrizzare l esecuzione del codice

Corso di Informatica

Introduzione a Matlab

Introduzione al linguaggio C Funzioni

Definizione di metodi in Java

Fondamenti di Informatica

LA RICORSIONE. Una funzione matematica è definita ricorsivamente quando nella sua definizione compare un riferimento a se stessa

Elementi di Calcolo Scientifico per l Ingegneria A.A

Informatica (A-K) 12. Linguaggio C -3

Lab 6 Info B. Luca M. Cassano Sadegh M. Astaneh Matteo Papini

Fondamenti di Informatica T. Linguaggio C: Stack e Ricorsione

Esercitazione 5. Procedure e Funzioni Il comando condizionale: switch

Esercitazione 2. Prima parte

DIPARTIMENTO DI ELETTRONICA, INFORMAZIONE E BIOIGNEGNERIA. INFORMATICA B Ingegneria Elettrica. Funzioni in Matlab

Informatica (A-K) 5. Algoritmi e pseudocodifica

PROGRAMMAZIONE: I sottoprogrammi

MATLAB c. Lucia Gastaldi Dipartimento di Matematica Lezione 4 (15 ottobre 2003)

Esercitazione 2. Prima parte

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

INFORMATICA A. Titolo presentazione sottotitolo. Laboratorio n 6 Dott. Michele Zanella Ing. Gian Enrico Conti

Informatica B

Introduzione al MATLAB c Parte 2 Funzioni

Laboratorio di Calcolo Numerico Laboratorio 3: Algoritmi stabili e instabili, Bisezione

Fondamenti di Informatica

% per essere certi che a <= b a = min(interval); b = max(interval);

Laboratorio di Informatica L-A 1

Risoluzione di un problema

12 Function Handles e Ricorsione in MATLAB

Pensiero Algoritmico. Lezione 3 23 Novembre Ripasso. Anatomia di un programma. Anatomia di un programma. Ozalp Babaoglu Università di Bologna

Strutture Dati. Luca Abeni

MATLAB Elementi di grafica Costrutti di programmazione

Ricorsione. La ricorsione consiste nella possibilità di definire una funzione in termini di se stessa

Metodi di Analisi dei Dati Sperimentali. AA 2009/2010 Pier Luca Maffettone. Elementi di Matlab

Pile Le pile: specifiche e realizzazioni attraverso rappresentazioni sequenziali e collegate. Pile e procedure ricorsive

Strutture Dati. Nicu Sebe. Informatica Nicu Sebe 1 / 27

La programmazione nel linguaggio JavaScript. Il programma

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

Operativamente, risolvere un problema con un approccio ricorsivo comporta

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

MATLAB Le funzioni. Funzioni. Funzioni. Funzioni

function f = fattoriale(n) f = 1; for ii = 2 : n f = f * ii; end

Funzioni in C. Funzioni. Strategie di programmazione. Funzioni in C. Come riusare il codice? (2/3) Come riusare il codice? (1/3)

Metodi numerici con elementi di Programmazione A.A

Ricorsione. DD cap. 5 pp KP cap. 5 pp

Programmazione a Oggetti e JAVA. Prof. B.Buttarazzi A.A. 2012/2013

Scilab. Introduzione a Scilab - Vettori. Corso di Informatica CdL: Chimica. Claudia d'amato.

definire definire una una funzione in termini di se stessa compare una chiamata alla funzione stessa identificare un caso base

definire definire una una funzione in termini di se stessa compare una chiamata alla funzione stessa identificare un caso base

Funzioni e Ricorsione

>> A = [1 2 3; 4 5 6; 7 8 9]; >> A

Rappresentazione degli algoritmi

Dinamica e Controllo dei Processi Energetici. AA 2009/2010 Pier Luca Maffettone. Elementi di Matlab

Strategie di programmazione

13 Ricorsione con MATLAB

Transcript:

Sottoprogrammi Diagrammi in MATLAB Informatica B - Prof. A Morzenti 1 / 44

Motivi per introdurre sottoprogrammi riusabilità (scrivere una sola volta codice usato più volte) astrazione (esprimere in modo sintetico operazioni complesse) estendibilità del linguaggio (non tutte operazioni incluse come predefinite) meccanismi per fare ciò chiamati sottoprogrammi assomigliano a interi programmi ma asserviti ad altri programmi per un sottoprogramma deve essere definito quale operazione astratta realizza come può essere identificato dal programma principale quali parametri coinvolge dati in ingresso come punto di partenza dei calcoli valori restituiti ai programmi che lo usano un sottoprogramma definito può essere utilizzato dal programma principale utilizzo è detto chiamata (o invocazione) del sottoprogramma In MATLAB i sottoprogrammi hanno la forma di funzioni dominio corrisponde a operandi/dati codominio corrisponde a valori calcolati 2 / 44

sintassi della definizione di funzione: testata + corpo Esempio: funzione fact per il calcolo del fattoriale function [f]=fact(n) f=1; for k=1:n f=f*k; end testata corpo: è la parte eseguibile testata contiene informazioni rilevanti per uso corretto del sottoprogramma lista dei risultati, tra parentesi quadre, separati da, matematicamente, il codominio della funzione identificatore del sottoprogramma lista degli argomenti, tra parentesi tonde, separati da, matematicamente, il dominio della funzione argomenti e risultati detti parametri formali se considerati dal punto di vista della funzione parametri attuali se considerati dal punto di vista del programma chiamante 3 / 44

Funzione utilizzata invocandola: >> x=fact(4) x =24 sintassi dell invocazione ispirata a notazione matematica una funzione, applicata a suoi argomenti, fornisce un valore del suo codominio nei programmi i valori denotati da espressioni chiamata di funzione sintatticamente è un espressione >> x=fact(2)+fact(3) x = 8 >> fact(fact(3)) ans = 720 Equivalente a >> y=fact(3); fact(y) ans = 720 4 / 44

Sintassi dell invocazione di una funzione identificatore della funzione lista dei parametri attuali racchiusa fra parentesi tonde parametri attuali: valori degli argomenti ai quali applicata funzione ogni parametro è un espressione qualsiasi (di tipo appropriato ) può essere una chiamata di funzione NB: parametri possono essere di tipo qualsiasi (senza alcuna restrizione) Se ci sono più parametri, corrispondenza tra formali e attuali determinata dall ordine primo formale primo attuale secondo formale secondo attuale etc. numero parametri attuali = numero parametri formali ovviamente, tipo dei parametri attuali compatibile con tipo dei formali Nel caso di più parametri in uscita, risultati raccolti usando la notazione dei vettori >> [x,y]=sumprod(4,5) x = 9 y = 20 function [s,p]=sumprod(a,b) s=a+b; p=a*b; 5 / 44

Dove si definisce (scrive) una funzione? In un M-file di tipo particolare detto file di funzione Ha estensione.m come i file di script File di funzione deve avere stesso nome della funzione che contiene iniziare con la definizione della funzione (NB: parola function va in minuscolo) ciò distingue da file di script trovarsi in una cartella che sta nel PATH di MATLAB Per evitare conflitti di nomi usare exist( nomefunzione ) restituisce 0 se la funzione non esiste, 0 altrimenti es. sin è una funzione predefinita (built-in) >> exist('sin') ans = 5 6 / 44

Esecuzione delle funzioni e passaggio dei parametri Comportamento dell interprete MATLAB durante esecuzione funzioni Consideriamo esempio >> r=12; s=42; [h,k]=mcdmcm(r, s) h = 6 k = 84 function [M, m]=mcdmcm(a, b) x=a; y=b; while x ~= y if x>y x=x-y; else y=y-x; end; end; M=x; m=a*b/m; Descrizione esecuzione fa uso di metafora delle macchine astratte una macchina principale per esecuzione programma chiamante una asservita per esecuzione funzione entrambe dotate di proprio insieme di variabili detto ambiente o stato di esecuzione 7 / 44

ambiente macchina principale contiene due variabili r e s, argomenti della chiamata (parametri attuali di ingresso) due variabili h e k cui sono assegnati i risultati (parametri attuali di uscita) ambiente della macchina asservita (ambiente locale della funzione) contiene i quattro parametri formali, due di ingresso, a e b, e due di uscita, M ed m sono a tutti gli effetti delle variabili locali alla funzione visibili solo al suo interno esistono indipendentemente da altre variabili anche omonime esterne altre due variabili locali x e y Effetto dell esecuzione di [h,k]=mcdmcm(r, s) macchina principale valuta espressione a destra dell assegnamento = calcolato il valore dei parametri attuali di ingresso creata macchina asservita passaggio dei parametri copiatura valore parametri attuali in ingresso (r ed s) nei corrispondenti parametri formali a e b ceduto il controllo alla macchina asservita (esecuzione macchina principale sospesa) esecuzione del corpo della funzione alla fine variabili M ed m hanno valore risultante dall esecuzione nell ambiente locale passaggio dei parametri copiatura all indietro dei parametri formali di uscita (M ed m) nei parametri attuali h e k controllo restituito a macchina principale, macchina asservita (con tutto il suo ambiente) distrutta 8 / 44

Sequenza nell esecuzione di [h,k]=mcdmcm(r, s) MCDmcm MCDmcm x: y: x: y: a: b: M:.. m: a:12 b:42 M: m: r:12 s:42 h: k: principale r:12 s:42 h: k: principale r:12 s:42 h: k: principale (1) (2) (3) MCDmcm MCDmcm MCDmcm x: 6 y: 6 x: 6 y: 6 x: 6 y: 6 a:12 b:42 M:6 m:84 M:12 m:42 M:6 m:84 M:12 m:42 M:6 m:84 r:12 s:42 h: k: principale (4) r:12 s:42 h:6 k:84 principale (5) r:12 s:42 h:6 k:84 principale (6) 9 / 44

Ambienti della macchina principale e di quella asservita sono disgiunti comunicano attraverso i parametri possono contenere variabili omonime, che rimangono distinte NB: dopo esecuzione di una funzione non rimane traccia del suo ambiente Es.: vrbli x e y locali a MCDmcm distinte da quelle dell ambiente principale, vble a indefinita fuori da MDDmcm >> x=12;y=42;[h,k]=mcdmcm(x,y) h = 6 k = 84 >> [x,y] ans = 12 42 >> a??? Undefined function or variable 'a'. function [M, m]=mcdmcm(a, b) x=a; y=b; while x ~= y if x>y x=x-y; else y=y-x; end; end; M=x; m=a*b/m; Es.: nessun pericolo di confusione tra variabili omonime nei due ambienti, comunicazione avviene mediante copiatura >> M=12;m=42;[a,b]=MCDmcm(M,m) a = 6 b = 84 >> Meglio comunque in generale evitare omonimie come queste, che creano confusione 10 / 44

Parametri di tipo array possibili in ingresso e anche in uscita occorre conoscere dimensioni dell array in ingresso funzione predefinita length(v) dà numero degli elementi di v array in uscita può essere costruito incrementalmente, come già visto altrove Esempio: function [pres, pos]=cerca(x cerca(x,, v) cerca scalare x in array v se x presente pres=1 altrimenti pres=0 pos=vettore con indici di tutti elem.ti di v uguali a x >> A=[1, 2, 3, 4, 3, 4, 5, 4, 5, 6] A = 1 2 3 4 3 4 5 4 5 6 >> [p, i]=cerca(4,a) p = 1 i = 4 6 8 >> function [pres, pos]=cerca(x, v) p=0; pos=[]; for i=1:length(v) if v(i)==x p=p+1; pos(p)=i; end end pres=p>0; 11 / 44

Parametri di tipo matrice (o array a n dimensioni) possibili in ingresso e anche in uscita occorre conoscere dimensioni del parametro in ingresso funzione predefinita ndims(v) dà numero n delle dimensioni di v funzione predefinita size(v) dà array con n valori: le dimensioni di v e.g., [R,C]=size(m) dà, in R e in C, num. righe e colonne della matrice m Esempio: function [t]=trasposta(m) crea matrice t con righe e colonne scambiate rispetto a ingresso m >> m=[1,2,3,4;5,6,7,8;9,10,11,12] m = 1 2 3 4 5 6 7 8 9 10 11 12 >> trasposta(m) ans = 1 5 9 2 6 10 3 7 11 4 8 12 function [t]=trasposta(m) [R,C]=size(m); for r=1:r for c=1:c t(c,r)=m(r,c); end; end 12 / 44

Parametri di tipo struct (ovviamente) ammessi: ma non c è (ahimè) controllo di tipi attezione a corrispondenza parametri attuali-formali, specie in ingresso Esempio: function [c]=polar2cart(p) da rappresentazione polare di punto nel piano a quella cartesiana >> P.ro=1; P.teta=pi/3 P = ro: 1 teta: 1.0472 >> Q=polar2cart(P) Q = x: 0.5000 y: 0.8660 NB!! >> R.to=1; R.teta=pi/3 R = to: 1 teta: 1.0472 >> Q=polar2cart(R)??? Reference to non-existent field 'ro'. Error in ==> polar2cart at 2 c.x=p.ro*cos(p.teta); ρ θ P function [c]=polar2cart(p) c.x=p.ro*cos(p.teta); c.y=p.ro*sin(p.teta); y x P 13 / 44

Esempio con ingresso array di strutture: Esempio: function [dm]=distmedia(a) distanza media dall origine dei punti (strutture con campi x e y) contenuti nell array a >> a.x=1;a.y=0;b.x=0;b.y=2; >> v=[a,b]; >> distmedia(v) ans = 1.5000 >> function [dm]=distmedia(a) s=0; for k=1:length(a) s=s+sqrt(a(k).x^2+a(k).y^2); end; dm=s/length(a); Una comoda possibilità per le funzioni con più risultati (parametri in uscita): Esempio: function [s,p]=sumprod(a,b), invocata con >>[x,y]=sumprod(4,5) Possibile restituire solo il primo dei valori (l altro viene perso) assegnando il risultato a uno scalare >> x=sumprod(4,5) x = 9 14 / 44

istruzione return Termina l esecuzione della funzione e restituisce il controllo al programma chiamante (usualmente questo avviene dopo l esecuzione dell ultima istruzione della funzione) Esempio d uso: funzione cercamultiplo cerca un multiplo di un numero v (assunto 0) in un array a, restituisce posizione p e valore m del multiplo se trovato (o coppia di zeri altrimenti) NB: se nell array ci sono più multipli se ne può restituire uno qualsiasi function [p,m]=cercamultiplo(v, a) for k=1:length(a) if mod(a(k),v)==0 p=k; m=a(k); return; %si restituisce il primo multiplo incontrato % evita ulteriori inutili calcoli end; end; p=0; m=0; %eseguite solo se non trovato alcun multiplo %versione senza istruzione return function [p,m]=cercamultiplonr(v, a) trovato=0; k=1; while k <= length(a) && ~trovato if mod(a(k),v)==0 p=k; m=a(k); trovato=1; end; k=k+1; end; if ~trovato p=0; m=0; end; NB: l istruzione return non è indispensabile si può sostituire con combinazioni di altre istruzioni, usando eventualmente variabili aggiuntive permette però di scrivere funzioni più compatte e leggibili 15 / 44

Funzioni che chiamano funzioni Finora assunto funzioni invocate dal programma cosiddetto chiamante o principale linea di comando script alternativa: istruzione di chiamata inclusa in una (altra) funzione caso molto interessante. con sviluppi importantissimi (ricorsione) Esempio semplice: calcolo del coefficiente binomiale n = k n! k! ( n k)! usiamo funzione fact(n) per il fattoriale definita in precedenza (NB: nessun conflitto tra parametro n di fact e parametro n di coefbin) function [c]=coefbin(n, k) f1=fact(n); f2=fact(k); f3=fact(n-k); c=f1/(f2*f3); 16 / 44

Esecuzione di coefbin(6,2) Si generano più macchine astratte asservite. che esistono simultaneamente solo quella creata per ultima è attiva ordine di terminazione delle macchine inverso a quello di inizio (gestione LIFO, Last In First Out) fact(6) fact(2) coefbin(6,2) coefbin(6,2) coefbin(6,2) coefbin(6,2) interprete comandi interprete comandi interprete comandi interprete comandi interprete comandi (1) (2) (3) (4) (5) fact(4) coefbin(6,2) coefbin(6,2) coefbin(6,2) interprete comandi interprete comandi interprete comandi interprete comandi (6) (7) (8) (9) 17 / 44

Confronto Funzioni vs. Script (1) FUNZIONI Hanno un proprio ambiente di esecuzione variabili locali distinte da quelle del chiamante variabili locali cessano di esistere al ritorno comunicazione mediante copiatura parametri Adatte a sviluppo sistematico di applicazioni complesse Unità di programma con alta coesione interna e interfacce minimali e chiaramente identificate SCRIPT NON hanno un proprio ambiente di esecuzione variabili dello script sono le stesse del chiamante variabili create nello script continuano a esistere comunicazione mediante scrittura/lettura variabili comuni Adatti a sviluppo esplorativo e prototipale 18 / 44

Confronto Funzioni vs. Script (2) Esempio: calcolo distanza tra due punti in piano cartesiano mediante script o funzione % script: file distscript.m dx = x2 x1; dy = y2 y1; d = sqrt(dx^2 + dy^2); quattro punti: a(1,1), b(1,2), c(3,2) e d(3,4); calcolata distanza tra a e b (=1) e tra c e d (=2) function [d] = distfunz(x1,y1,x2,y2) dx = x2 x1; dy = y2 y1; d= sqrt(dx^2 + dy^2); >> ax = 1; ay = 1; bx = 1; by = 2; >> cx = 3; cy = 2; dx = 3; dy = 4; variabili usate per comunicare con lo script: - x1, y1, x2, y2 per trasmettere allo script i punti di cui calcolare la distanza - d per restituire al chiamante il risultato >> x1=ax; y1=ay; x2=bx; y2=by; >> distscript >> Dab = d Dab = 1 >> x1=cx; y1=cy; x2=dx; y2=dy; >> distscript >> Dcd = d Dcd = 3.1623 >> ERRATO >> Dab=distFunz(ax,ay,bx,by) Dab = 1 >> Dcd=distFunz(cx,cy,dx,dy) Dcd = 2 >> CORRETTO 19 / 44

Confronto Funzioni vs. Script (3) Codice che usa la funzione è molto più conciso: incorpora parte di passaggio parametri Perchè lo script dà un risultato errato? Problema con variabili dx e dy: hanno due ruoli nel chiamante rappresentano coordinate del punto d nello script differenze delle ascisse e delle ordinate dei due punti prima esecuzione dello script modifica coordinate dx e dy del punto d: diventa d(0,1) seconda calcola distanza tra il punto c(3,2) e quello erroneo d(0,1): viene 10 = 3.1623 NB: l errore passa inosservato se non si controlla il risultato Morale: script e suo programma chiamante non possono essere definiti indipendentemente occorre individuare variabili usate da entrambi script e chiamante per la comunicazione le altre variabili devono essere usate da uno solo dei due 20 / 44

Introduzione alla programmazione ricorsiva chiamata ricorsiva di sottoprogrammi un sottoprogramma P chiama lo stesso P direttamente o indirettamente (e.g., P chiama Q che chiama P) sembra circolo vizioso per molti problemi soluzione per un caso generico ricavata della soluzione di altro caso, più semplice, dello stesso problema Esempi di problemi con formulazione e soluzione ricorsiva Funzione fattoriale f(n) = n! = n * (n-1) * (n-2) *... 3 * 2 * 1 può essere definito RICORSIVAMENTE come segue: Se n=0 allora f(n) = 1 (base della ricorsione) Se n>0 allora f(n) = n * f(n-1) (passo ricorsivo) 21 / 44

Sequenza numeri di Fibonacci F = {f 1,..., f n } (modello di crescita di animali in successive generazioni) f 1 = 1 f 2 = 1 Per n > 2, f n = f n 1 + f n 2 (caso base) (caso base) (caso ricorsivo, NB: ricorsione doppia) da cui per esempio f 1 = 1 f 2 = 1 f 3 = f 2 + f 1 = 1 + 1 = 2 f 4 = f 3 + f 2 = 2 + 1 = 3 22 / 44

massimo comune divisore, MCD(m, n) di due numeri m ed n in base all algoritmo di Euclide se m = n, MCD(m, n) = m (caso base) se m > n, MCD(m, n) = MCD(m-n, n) (caso risorsivo) se m < n MCD(m, n) = MCD(m, n-m) (caso risorsivo) ciò perchè se m > n divisori comuni a m e n coincidono con divisori comuni a m n e n ragionamento può essere ripetuto prima o poi si arriva a una coppia di numeri uguali 30 18 12 18 12 6 6 6 23 / 44

Programmazione delle funzioni ricorsive funzione non ricorsiva per il fattoriale function [f]=fact(n) f=1; for i=1:n f=f*i; end versione ricorsiva basata su definizione induttiva n! = n (n 1)!, con 0! = 1 per convenzione function [f]=factric(n) if (n==0) f=1; else f=n*factric(n-1); end simulazione del calcolo di factric(3) 3 = 0? No. calcola fattoriale di 2 e moltiplica per 3. 2 = 0? No. calcola fattoriale di 1 e moltiplica per 2. 1 = 0? No. calcola fattoriale di 0 e moltiplica per 1. 0 = 0? Sì. fattoriale di 0 è 1. fattoriale di 1 è 1 fattoriale di 0, cioè 1 1 = 1. fattoriale di 2 è 2 fattoriale di 1, cioè 2 1 = 2. fattoriale di 3 è 3 fattoriale di 2, cioè 3 2 = 6. 24 / 44

Gestione a pila degli ambienti locali delle funzioni factric n:0 f:.. factric n:1 f:.. factric n:1 f:.. factric n:2 f:.. factric n:2 f:.. factric n:2 f:.. factric n:3 f:.. factric n:3 f:.. factric n:3 f:.. factric n:3 f:.. (1) (2) (3) (4) factric n:0 f:1 factric n:1 f:.. factric n:1 f:1 factric n:2 f:.. factric n:2 f:.. factric n:2 f:2 factric n:3 f:.. factric n:3 f:.. factric n:3 f:.. factric n:3 f:6 (5) (6) (7) (8) NB: ambienti locali gestiti in modo LIFO (Last In First Out): cancellati in ordine inverso a quello un cui sono stati creati: si usa una struttura di dati detta PILA 25 / 44

Terminazione dei sottoprogrammi ricorsivi rischio di catene infinite di chiamate condizioni NECESSARIE (non sufficienti) per evitarlo le chiamate ricorsive siano condizionate ( una chiamata può NON generarne un altra) le chiamate ricorsive abbiano argomenti RIDOTTI Controesempi function [f]=factric(n) f=n*factric(n-1); Catena infinita di chiamate con argomento decrescente function [f]=factric(n).factric(n); Catena infinita di chiamate identiche (NB: quella giusta è questa) function [f]=factric(n) if (n==0) f=1; else f=n*factric(n-1); end 26 / 44

Calcolo del MCD con algoritmo di Euclide Versione iterativa 30 18 Versione ricorsiva function [M]=MCDeuclid(m,n) while m ~= n if m>n m=m-n; else n=n-m; end end M=m; 12 12 18 6 6 6 function [M]=MCDeuclidRic(m,n) if m==n M=m; else if m>n M = MCDeuclidRic(m-n,n); else M = MCDeuclidRic(m,n-m); end end 27 / 44

Calcolo numero di Fibonacci di indice n Versione che calcola n-simo numero function [f]=fib (n) if n==1 n==2 f = 1; else f = fib(n - 2) + fib(n - 1); end Esercizio suggerito: confrontare le due versioni riguardo all efficienza (uso delle risorse, memoria e tempo) Calcola la lista dei primi n numeri di Fibonacci, n>1 function [fl]=fiblist(n) fl(1)=1; fl(2)=1; for k=3:n fl(k)=fl(k-2)+fl(k-1); end Versione che calcola ogni numero della lista in modo ricorsivo function [fl]=fiblist(n) for k=1:n fl(k)=fib(k); end 28 / 44

Ricorsione Multipla Funzione doppiamente ricorsiva: due chiamate ricorsive (eseguite una dopo l altra) function [f]=fib (n) if n==1 n==2 f=1; else f=fib(n-2) + fib(n-1); end Soluzione elegante ma dispendiosa: numero esorbitante di chiamate ricorsive fib(6) fib(4) fib(5) fib(2) fib(3) fib(3) fib(4) fib(1) fib(2) fib(1) fib(2) fib(2) fib(3) fib(1) fib(2) Provate a far calcolare fib(5), poi fib(10), fib(15), fib(20), fib(25), fib(30),... Meglio usare una soluzione non ricorsiva... 29 / 44

Un problema interessante con una semplice soluzione ricorsiva 1 2 3 1 2 3 1 2 3 1 2 3 (a) (b) (c) (d) 1 2 3 1 2 3 1 2 3 1 2 3 (e) (f) (g) (h) Torri di Hanoi Obiettivo: ricomporre pila di dischetti su un piolo diverso - spostando un disco alla volta - restrizione: mai appoggiare un dischetto su un altro di diametro inferiore Soluzione: per spostare k dischetti da un piolo a un altro usa il terzo piolo come supporto intermedio sposta su di esso la pila di k-1 dischi (riapplica ricorsivamente se k-1>1) poi sposta disco più grande sul piolo di destinazione poi sposta pila di k-1 elementi dal piolo intermedio a quello di destinazione. 30 / 44

Soluzione in codice MATLAB con simulazione function []=hanoi(n, da, a, per) if (n>1) hanoi(n-1, da, per, a); end; fprintf('\n sposta un disco dal piolo %d al piolo %d \n', da, a); if (n>1) hanoi(n-1, per, a, da); end; hanoi(3, 1, 2, 3) hanoi(2, 1, 3, 2) hanoi(2, 3, 2, 1) hanoi(1, 1, 2, 3) hanoi(1, 2, 3, 1) hanoi(1, 3, 1, 2) hanoi(1, 1, 2, 3) >> hanoi(3, 1, 2, 3) sposta un disco dal piolo 1 al piolo 2 sposta un disco dal piolo 1 al piolo 3 sposta un disco dal piolo 2 al piolo 3 sposta un disco dal piolo 1 al piolo 2 sposta un disco dal piolo 3 al piolo 1 sposta un disco dal piolo 3 al piolo 2 sposta un disco dal piolo 1 al piolo 2 >> 31 / 44

Cosa si può ottenere combinando ricorsione e iterazione? Esempio: Costruzione ricorsiva delle permutazioni di un insieme di numeri, memorizzato in un vettore, secondo lo schema in figura 1 2 3 2 3 1 3 1 2 3 2 3 1 2 1 matematicamente, permutazioni({1, 2, 3}) = {<1 2 3>, <1 3 2>, <2 1 3>, <2 3 1>, <3 1 2>, <3 2 1>} due funzioni: quella ausiliaria ricorsiva fa tutto il lavoro function []=permutazioni(s) ricperm(length(s), [], s); function []=ricperm(n, p, s) if n>0 for k = s if all( p ~= k ) p1=p; p1(end+1)=k; ricperm(n-1, p1,s); end end else p end n.elem.da aggiungere perm. costruita finora ins.elementi da permutare aggiunge solo elementi non già presenti senza il ; stampa vetrore p >> permutazioni([1 2 3]) p = 1 2 3 p = 1 3 2 p = 2 1 3 p = 2 3 1 p = 3 1 2 p = 3 2 1 >> 32 / 44

versione che usa la cancellazione di elementi nei vettori function []=permdel(s) RPD ([], s); function []=RPD(p, s) if ~isempty(s) for k=1:length(s) p1=p; p1(end+1)=s(k); s1=s; s1(k)=[]; RPD(p1, s1); end else p end perm. costruita finora elementi da inserire nella permutaizone aggiungi s(k) in fondo a p1 cancella s(k) dalla posizione k di s1 permdel([1 2 3]) RPD([],[1 2 3]) RPD([1],[2 3]) RPD([2],[1 3]) RPD([3],[1 2]) RPD([1 2],[3]) RPD([1 3],[2]) RPD([2 1],[3]) RPD([2 3],[1]) RPD([3 1],[2]) RPD([3 2],[1]) RPD([1 2 3],[]) RPD([1 3 2],[]) RPD([2 1 3],[]) RPD([2 3 1],[]) RPD([3 1 2],[]) RPD([3 2 1],[]) 33 / 44

Variabili funzione e funzioni di ordine superiore Versioni recenti di Matlab definiscono in modo pieno il tipo funzione, permettendo di - assegnare a variabili valori di tipo funzione - definire funzioni che ricevono parametri di tipo funzione Cosa si può fare con un valore di tipo funzione? - assegnarlo a una variabile (quindi passarlo come parametro) - applicarlo a opportuni argomenti: si ottiene una invocazione della funzione Valori di tipo funzione denotati da variabili dette handle (riferimento / maniglia) A una handle possono essere assegnati valori di tipo funzione in due modi (1) indicando il nome di una funzione esistente (definita dall utente o predefinita) (2) mediante la definizione ex novo di una funzione anonima (1) È semplice: nome della funzione (posto dopo @ ) denota la funzione stessa >> f=@fact f = @fact >> f(4) ans = 24 >> seno=@sin seno = @sin >> seno(pi/2) ans = 1 34 / 44

(2) definizione ex novo di una funzione anonima insieme ad assegnamento a una handle >> sq=@(x)x^2 sq = @(x)x^2 >> sq(8) ans = 64 Espressione di tipo funzione: 1. simbolo @ 2. lista dei parametri di ingresso, tra parentesi tonde 3. espressione che dà il risultato come funzione degli ingressi (NB possibile definire funzioni a più valori: escamotage di restituire un vettore ) Se il parametro attuale di una funzione F è di tipo funzione allora il parametro formale f - è una handle - può essere usato per invocare la funzione passata tramite il parametro La funzione F è una funzione di ordine superiore Possibile in Matlab programmare funzioni di ordine superiore per realizzare funzioni parametriche rispetto a un operazione rappresentata a sua volta da una funzione 35 / 44

Esempietto di programmazione funzionale funzione di ordine superiore maxdifunzione riceve come parametri f funzione di una variabile reale gli estremi a e b di un intervallo valore d (da usare come passo di incremento) trova il valore massimo M e la sua ascissa (approssimati) della funzione f in [a..b] applicandola in tutti i punti tra a e b, con un intervallo di scansione d >> f=@(x)x^3-3*x; >> maxdifunzione(f, -2, 2, 0.01) ans = 2 >> function [M,xM]=maxDiFunzione(f, a, b, d) xm=a; M=f(xM); for x = a+d:d:b if f(x)>m xm=x; M=f(x); end; end; end Facile generalizzare con esempi di analisi funzionale: e.g., funzioni di ordine superiore che calcolano integrali (superfici, volumi,...) 36 / 44

Diagrammi a due dimensioni Diagramma = insieme di coppie rappresentanti le coordinate dei suoi punti Si usano vettori per contenere sequenze ordinate dei valori di ognuna delle coordinate plot(x,y) disegna diagramma cartesiano dei punti che hanno valori delle ascisse in x, delle ordinate in y e li congiunge con una linea, per dare continuità al grafico funzioni xlabel per visualizzare nome asse ascisse, ylabel per ordinate, title per il titolo >> x = -10:0.1:10; >> y=x.^3; >> plot(x,y); >> xlabel('ascisse'); >> ylabel('ordinate'); >> title('cubica'); >> x=[-8:0.1:8]; >> y= sin (x)./ x; >> plot(x, y); >> xlabel('ascisse'); >> ylabel('ordinate'); 1000 800 cubica 1 0.8 600 400 0.6 ordinate 200 0-200 ordinate 0.4 0.2-400 0-600 -800-1000 -10-8 -6-4 -2 0 2 4 6 8 10 ascisse -0.2-0.4-8 -6-4 -2 0 2 4 6 8 ascisse 37 / 44

NB: diagramma = insieme di coppie rappresentanti le coordinate dei suoi punti con plot(x,y) x non contiene necessariamente un intervallo lineare uniforme di valori y non è necessariamente funzione di x sia x sia y possono essere funzioni di qualche altro parametro Vediamo due esempi: >> t=[0:pi/100:2*pi]; >> x=cos(t); >> y=sin(t); >> plot(x,y); >> xlabel('ascisse-x'); >> ylabel('ordinate-y'); 10*pi 5 giri t 10*pi dist.max da origine 31,4 >> t=[0:pi/100:10*pi]; >> x=t.* cos(t); >> y=t.* sin(t); >> plot(x,y); >> xlabel('ascisse-x'); >> ylabel('ordinate-y'); cosa possiamo aspettarci come grafici? 38 / 44

1 30 0.8 0.6 20 0.4 10 0.2 ordinate-y 0 ordinate-y 0-0.2-0.4-10 -0.6-20 -0.8-1 -1-0.8-0.6-0.4-0.2 0 0.2 0.4 0.6 0.8 1 ascisse-x -30-30 -20-10 0 10 20 30 40 ascisse-x 39 / 44

Diagrammi lineari a tre dimensioni Generalizzazione di quello a due: insieme di terne etc plot3(x,y,z) per digramma cartesiano con x ascisse, y ordinate, z quote funzioni xlabel, ylabel, zlabel, title >> t = 0:0.1:10*pi; >> plot3 (t.*sin(t), t.*cos(t), t); >> xlabel('ascisse'); >> ylabel('ordinate'); >> zlabel('quote'); quote 40 30 20 10 0 40 20 0 ordinate -20-40 -40-20 0 ascisse 20 40 40 / 44

Diagrammi tridimensionali a superficie Funzione reale di due variabili reali z = f (x, y) rappresentata in uno spazio cartesiano tridimensionale è una superficie funzione mesh genera superficie, a partire da tre argomenti: matrici xx, yy, zz che contengono ascissa (valore di x), ordinata (y) e quota (z) per ogni punto di una griglia corrispondente a un rettangolo del piano xy il rettangolo è identificato dalla coppia di matrici xx e yy Le due matrici, xx, e yy, si ottengono, mediante la funzione meshgrid meshgrid(x,y x,y), a partire da vettori, x e y, che contengono i valori delle ascisse e delle ordinate il rettangolo nel piano è determinato da x e y l insieme delle coordinate dei suoi punti è il prodotto cartesiano di x e y 41 / 44

Come funziona meshgrid? [xx xx,yy yy]=meshgrid =meshgrid(x,y x,y) A partire da vettori, x e y, che contengono i valori delle ascisse e delle ordinate genera due matrici entrambe di legth(y) righe length(x) colonne la prima, xx, contiene, ripetuti in ogni riga, i valori di x la seconda, yy, contiene, ripetuti in ogni colonna, i valori di y (y trasposta) Semplice esempio: funzione z = x + y, grafico in 6 punti di ascisse {1, 3, 5} e ordinate {2, 4} >> x=[1, 3, 5]; >> y=[2, 4]; >> [xx,yy]=meshgrid(x,y); >> zz=xx+yy; >> mesh(xx,yy,zz); >> xlabel('ascisse-x'); >> ylabel('ordinate-y'); >> zz zz = 3 5 7 5 7 9 >> xx xx = 1 3 5 1 3 5 >> yy yy = 2 2 2 4 4 4 Punti di coordinate (x,y) (1,2) (3,2) (5,2) (1,4) (3,4) (5,4) hanno coordinate (x,y,z) (1,2,3) (3,2,5) (5,2,7) (1,4,5) (3,4,7) (5,4,9) (NB: z=x+y) 9 8 7 6 5 4 3 4 3.5 3 ordinate-y 2.5 2 1 2 5 4 3 ascisse-x 42 / 44

Vantaggio del modus operandi: vettore con le z ottenuto con espressione uguale alla forma algebrica della funzione In pratica i vettori x e y da dare in pasto a meshgrid non si producono a mano si ottengono con costrutto [vmin : δ : vmax] o altri simili tipicamente si adotta una spaziatura uniforme tra i valori attenzione a non usare valore δ troppo piccolo, altrimenti memoria insuffciente Altro semplice esempio: >> x=[1:1:3]; >> y=x; >> [xx,yy]=meshgrid(x,y); >> zz=xx+yy; >> mesh(xx,yy,zz); >> xlabel('x'); >> ylabel('y'); >> zlabel('z'); 6 z 5 4 3 2 3 2.5 3 2.5 2 Un po meno semplice: disegnare un paraboloide 1.5 1 y 1 x 40 30 quote-z >> x=[-4:0.05:4]; >> y=x; >> [xx,yy]=meshgrid(x,y); >> zz=xx.^ 2 + yy.^ 2; >> mesh(xx,yy,zz); >> xlabel('ascisse-x'); >> ylabel('ordinate-y'); >> zlabel('quote-z'); 2 1.5 20 10 0 4 2 4 2 0 0-2 ordinate-y -2-4 -4 ascisse-x 43 / 44

Il gioco può anche essere divertente: disegnamo un grafico a sombrero (NB: rotazione di quello a p.35) >> tx=[-8:0.1:8]; >> ty=tx; >> [xx, yy] = meshgrid (tx, ty); >> r = sqrt (xx.^ 2 + yy.^ 2); >> tz = sin (r)./ r; >> mesh (tx, ty, tz); >> xlabel('ascisse'); >> ylabel('ordinate'); >> zlabel('quote'); 1 quote 0.5 0-0.5 10 5 10 5 0 0-5 ordinate -5-10 -10 ascisse 44 / 44