Facoltà di Ingegneria Industriale Salvo Daniele Valente Dipartimento di Elettronica e Informazione Laurea in Ingegneria Energetica, Meccanica e dei Trasporti Matlab/Octave - Esercitazione 3 ‣ funzioni ‣ definizione ed invocazione delle funzioni ‣ semantica dell’invocazione ‣ ambiente locale e globale ‣ grafici 3D ‣ variabili di tipo funzione Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 1 Richiami teorici Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 In Matlab/Octave, una funzione è una sequenza di comandi che: ‣ ha un nome ‣ può essere invocata ‣ è influenzata da parametri definiti dal chiamante ‣ produce un risultato Questo consente di: ‣ scrivere un codice modulare organizzato ‣ riutilizzare una porzione di codice più volte senza riscrivere il codice stesso ‣ Suddividere operazioni complesse in un insieme di operazioni semplici Definizione di una funzione La prima riga del file deve essere del tipo: function [output1 output2 ...] = nome_funzione(input1, input2, ...) Invocazione di una funzione [output1 output2 ...] = nome_funzione(input1, input2, ...) Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 2 Richiami teorici Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Ogni funzione ha associato un record di attivazione che contiene: ‣ tutti i dati relativi all’ambiente locale della funzione ‣ l’indirizzo di ritorno del programma chiamante ‣ altri dati I record di attivazione delle funzioni sono memorizzati in una porzione della memoria di lavoro chiamata stack. Stack Script principale ... Workspace chiama f1 record di attivazione di f1 - 3 record di attivazione di f2 - 2 record di attivazione di f1 - 2 f1 f2 chiama f2 chiama f1 record di attivazione di f2 record di attivazione di f1 workspace Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 3 Esercizio 1 Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Scrivere un programma che chiede all'utente di inserire un numero positivo (nel caso in cui il numero non sia positivo ripetere inserimento). -Verifica se il numero è perfetto; -in caso contrario dice se è abbondante o difettivo. Un numero è perfetto se corrisponde alla somma dei suoi divisori, escluso se stesso; abbondante se è maggiore della somma dei suoi divisori; altrimenti difettivo. -Richiede un altro numero e controlla se i due numeri sono amici. a,b sono amici se (somma dei divisori di a) = b e viceversa. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 4 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Script principale - Parte 1 n1 = inserisciNumero(); [p,a] = controllaSePerfetto(n1); if(p) disp([num2str(n1), ' è perfetto']) else disp([num2str(n1), ' non è perfetto']) if(a) disp([num2str(n1), ' è abbondante']) else disp([num2str(n1), ' non è abbondante']) end end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 5 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Chiedo in input un numero e contemporaneamente controllo se è positivo. Nel caso non lo sia, ripeto l’operazione. n1 = inserisciNumero(); Tutte le specifiche riguardanti l’immissione di un numero positivo da parte dell’utente, possono essere soddisfatte con una sola istruzione. Questo è possibile se l’istruzione è una funzione. Di seguito la definizione della funzione inserisciNumero che analizzaremo successivamente nel dettaglio. function numero = inserisciNumero() Controllo se il numero inserito è perfetto, abbondante o difettivo. Anche queste operazioni possono essere racchiuse nella funzione: [p,a] = controllaSePerfetto(n1); function [perfetto,abbondante] = controllaSePerfetto(numero) Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 6 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale La funzione controllaSePerfetto analizza numero e pone p=1 se numero è perfetto, a=1 se abbondante e a=0 se difettivo. In base al risultato fornito dalla funzione visualizzo sulla command window la stringa corrispondente. if(p) disp([num2str(n1), ' è perfetto']) else disp([num2str(n1), ' non è perfetto']) if(a) disp([num2str(n1), ' è abbondante']) else disp([num2str(n1), ' non è abbondante']) end end L’esecuzione dello script principale è terminata. Vediamo ora nel dettaglio tutte le funzioni che sono state invocate, iniziando da inserisciNumero. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 7 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 inserisciNumero Definisco la funzione specificandone il nome, i parametri di input ed i parametri di output. function numero = inserisciNumero() Nel nostro caso la funzione insericiNumero non ha parametri di input. Quest’ultimi le vengono passati da tastiera tramite il comando input. % % % % % % numero = inserisciNumero() controlla che il numero inserito sia effettivamente positivo intero uno scalare I commenti che seguono (o precedono) la definizione della funzione costituiscono l’help della funzione stessa. Provare a digitare sulla commad window >>help inserisciNumero. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 8 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 inserisciNumero Per essere sicuri che la funzione venga individuata ed eseguita da Matlab/Octave è necessario: ‣ porla nella stessa cartella dello script principale (consigliato) o ‣ aggiungere la cartella di lavoro nei percorsi in cui Matlab/ Octave cerca le funzioni: ‣ usare il comando addpath ‣ specificare il percorso tramite il menu a tendina: File/ Set Path (solo Matlab) Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 9 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 inserisciNumero Chiedo in input il numero controllando che tale numero: ‣ non sia negativo: numero<0 ‣ non sia decimale: round(numero)~=numero ‣ non sia un vettore: max(size(numero))>1 numero = input(' inserisci un intero positivo '); while(numero<0|round(numero)~=numero|max(size(numero))>1) numero = input(' inserisci un intero positivo '); end A questo punto l’esecuzione della funzione inserisciNumero è terminata. Lo stack riporta l’esecuzione allo script principale. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 10 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 controllaSePerfetto Vediamo nel dettaglio la seconda funzione chiamata dallo script principale. function [perfetto,abbondante] = controllaSePerfetto(numero) % function [perfetto,abbondante]=controllaSePerfetto(numero) % % perfetto= 1 numero perfetto % perfetto= 0 altrimenti Si noti che i nomi delle variabili differiscono dalla chiamata della funzione alla definizione della funzione stessa. Questo è possibile perchè n1, p ed a sono variabili globali mentre perfetto, abbondante e numero sono variabili locali, definite unicamente all’interno della funzione. Quando l’esecuzione passa dallo script principale alla funzione, viene automaticamente operata l’assegnazione: numero = n1 Quando l’esecuzione ritorna allo script principale, invece, le assegnazioni sono: p = perfetto a = abbondante Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 11 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 controllaSePerfetto La funzione controllaSePerrfetto chiama immediatamente un’altra funzione: sommaDivisori. somma = sommaDivisori(numero); Questa funzione prende in input il numero specificato dall’utente e ne calcola la somma dei divisori. Inizializzo le due variabili d’uscita e controllo se il numero è perfetto. In tal caso pongo ad 1 la variabile perfetto. perfetto=0; abbondante=[]; if (somma==numero) perfetto=1; end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 12 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 controllaSePerfetto Controllo se il numero è abbondante o difettivo ed assegno il relativo valore ad abbondante. if(somma>numero) abbondante=1; else abbondante=0; end Vediamo ora nel dettaglio come opera la funzione sommaDivisori, chiamata da controllaSePerfetto. function somma = sommaDivisori(numero) % function somma=sommaDivisori(numero) % % restituisce la somma dei divisori di numero % Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 13 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale controllaSePerfetto MATLAB/Octave - Esercitazione 3 sommaDivisori Il numero di divisori di numero dev'essere necessariamente minore o uguale alla (metà di numero) + 1. I numeri maggiori di numero/2 non possono dividere il numero stesso. somma = 0; ii = 1; while(ii<numero/2+1) if(mod(numero,ii)==0) somma = somma + ii; end ii = ii+1; end La funzione mod(x, y) restutuisce il resto della divisione x./y. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 14 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Script principale - Parte 2 La seconda parte dell’esercizio ci chiede nuovamente di prendere in ingresso un numero inserito da utente. Per farlo non occorre scrivere nuovo codice, sarà sufficiente richiamare la funzione già invocata nella prima parte. n2=inserisciNumero(); Controllo se n1 e n2 sono amici attraverso l’invocazione della funzione amici=controllaSeAmici(n1,n2); Visualizzo i risultati sulla command window if(amici) disp([num2str(n1), ' e ', num2str(n2),' sono amici']) else disp([num2str(n1), ' e ', num2str(n2),' non sono amici']) end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 15 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione Script principale MATLAB/Octave - Esercitazione 3 controllaSeAmici La funzione controllaSeAmici richiama la funzione sommaDivisori per due volte al suo interno. Ricordiamo che, per ogni invocazione di funzione, ne viene creata un’istanza (una copia). L’esecuzione delle due istanze sono tra loro indipendenti. function amici=controllaSeAmici(numero1,numero2) % % controlla se i due numeri sono amici % amici=0; if (numero1==sommaDivisori(numero2)& numero2==sommaDivisori(numero1)) amici=1; end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 16 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 1 - Codice completo % Script principale n1 = inserisciNumero(); [p,a] = controllaSePerfetto(n1); if(p) disp([num2str(n1), ' è perfetto']) else disp([num2str(n1), ' non è perfetto']) if(a) disp([num2str(n1), ' è abbondante']) else disp([num2str(n1), ' è difettivo']) end end n2=inserisciNumero(); amici=controllaSeAmici(n1,n2); if(amici) disp([num2str(n1), ' e ', num2str(n2),' sono amici']) else disp([num2str(n1), ' e ', num2str(n2),' non sono amici']) end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 17 Esercizio 1 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 1 - Codice completo function numero=inserisciNumero() % numero=inserisciNumero() % % controlla che il numero inserito sia effettivamente % positivo % intero % uno scalare numero=input(' inserisci un intero positivo '); % controllo che il numero sia intero positivo while(numero<0|round(numero)~=numero|max(size(numero))>1) numero=input(' inserisci un intero positivo '); end function [perfetto,abbondante] = controllaSePerfetto(numero) % perfetto= 1 numero perfetto % perfetto= 0 altrimenti somma = sommaDivisori(numero); perfetto = 0; abbondante = []; if (somma==numero) perfetto = 1; end if(somma>numero) abbondante = 1; else abbondante = 0; end function amici=controllaSeAmici(numero1,numero2) % % controlla se i due numeri sono amici % amici=0; if (numero1==sommaDivisori(numero2)& numero2==sommaDivisori(numero1)) amici=1; end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione function somma = sommaDivisori(numero) % restituisce la somma dei divisori di numero somma = 0; ii = 1; while(ii<numero/2+1) if(mod(numero,ii)==0) somma = somma + ii; end ii = ii+1; end Informatica B - Esercitazione 10 del 10/12/2010 18 Esercizio 2 Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Si considerino due matrici di interi A e B, di uguali dimensioni. Diciamo che A domina B se, confrontando i valori in posizioni corrispondenti, risulta che il numero dei valori in A maggiori dei corrispondenti valori in B è più grande del numero di quelli di B maggiori dei corrispondenti in A ed inoltre gli elementi corrispondenti non sono mai uguali (se due elementi corrispondenti sono uguali la dominanza non è definita). Si codifichi la funzione domina() che riceve le matrici come parametri e restituisce 1 se la prima domina la seconda, -1 se la seconda domina la prima, 0 altrimenti. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 19 Esercizio 2 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Creo le due matrici casuali in modo che abbiano la stessa dimensione. A = round(20*rand(10, 10)); B = round(20*rand(size(A))); Definisco la funzione domina per confrontare A con B. risultato = domina(A, B); Analizzo il risultato fornito e stampo sulla command window il risultato corrispondente. switch(risultato) case 1 disp('A domina B'); case -1 disp('B domina A'); case 0 disp('dominanza non definita') end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 20 Esercizio 2 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Funzione domina Definisco la funzione secondo lo standard di Matlab/Octave function esito = domina(M1, M2) Confronto le due matrici tramite l’operatore logico >. Per entrambi i confronti, il risultato sarà una matrice logica di dimensioni uguali ad M1 ed M2. X = (M1 > M2); Y = (M2 > M1); Controllo quanti elementi di A sono maggiori di B e genero il risultato corrispondente. if(sum(X(:)) > sum(Y(:))) esito = 1; elseif (sum(X(:)) < sum(Y(:))) esito = -1; else esito = 0; end L’istruzione X(:) srotola la matrice X in un vettore nel senso delle colonne. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 21 Esercizio 2 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 2 - Codice completo % Script principale A = rand(10, 10); B = rand(size(A)); risultato = domina(A, B); switch(risultato) case 1 disp('A domina B'); case -1 disp('B domina A'); case 0 disp('dominanza non definita') end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione function esito = domina(M1, M2) X = (M1 > M2); Y = (M2 > M1); if(sum(X(:)) > sum(Y(:))) esito = 1; elseif (sum(X(:)) < sum(Y(:))) esito = -1; else esito = 0; end Informatica B - Esercitazione 10 del 10/12/2010 22 Esercizio 3 Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Dato un array quotaX di 365 valori interi, che rappresentano le quotazioni nell’anno solare corrente del titolo azionario X, si vuole realizzare un programma in grado di: -inizializzare il contenuto dell’array quotaX con valori letti da standard input che devono essere compresi tra 1 e 100 (estremi inclusi), scartando eventuali valori fuori dall’intervallo (i valori esterni all’intervallo saranno posti uguali all’estremo più prossimo). -Salvare in un’ opportuna variabile di tipo struttura la quotazione massima e il primo giorno (espresso come posizione nell’array) in cui tale quotazione è stata memorizzata. -Determinare e stampare a video il numero di periodi dell’anno in cui il titolo si è mantenuto costante (ossia, quante volte la medesima quotazione si è presentata in giorni successivi). Ad esempio, se le quotazioni fossero 10 10 15 14 12 12 1 8 9 9 12 12…, il titolo avrebbe avuto 4 periodi di quotazione costante. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 23 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Chiedo all’utente di inserire in input le quote del titolo tramite la funzione inizializzaQuotazioni(). quotaX = inizializzaQuotazioni(); La funzione non ha nessun parametro di ingresso perchè non ne necessita. I suoi parametri di ingresso saranno quelli inseriti dall’utente. Individuo la quotazione massima del titolo ed il giorno in cui si è verificata. [quotaXmax.valore quotaXmax.giorno] = max(quotaX); disp(' ') disp(['Quota massima raggiunta: ' num2str(quotaXmax.valore)]); disp(['nel giorno: ' num2str(quotaXmax.giorno)]); Utilizzo la funzione predefinita di Matlab/Octave [y, i] = max(x). Il suo help ci dice che, nel caso in cui x sia un vettore, la funzione pone in y il valore massimo di x e in i la sua posizione. Nel caso in cui y si presenti più volte, i riporterà la posizione della prima occorrenza. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 24 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Script principale Individuo i periodi in cui il titolo ha avuto quotazione costante e quanto sono durati, tramite la funzione quotaCostante(). [valore giorni] = quotaCostante(quotaX); disp(' ') disp(['Quote periodiche: ' num2str(valore)]); disp(['di giorni: ' num2str(giorni)]); Qui termina lo script principale. Vediamo nel dettaglio le funzioni che si sono utilizzate. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 25 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Funzione inizializzaQuotazioni() Definisco la funzione e chiedo in input i le quotazioni del titolo. function quota = inizializzaQuotazioni() quota = input('inserire il vettore delle quotazioni: '); Controllo che nel vettore inserito ci siano effettivamente 365 valori. Finché la sua lunghezza non è pari a 365, continuo a chiederne l’inserimento. while(length(quota) ~= 365) disp(['Sono stati inseriti' num2str(length(quota)) ' valori.... Inserire 365 valori']) disp(' ') quota = input('inserire il vettore delle quotazioni: '); end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 26 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Funzione inizializzaQuotazioni() Controllo che i valori siano compresi nell’intervallo [1 100]. I valori esterni all’intervallo saranno posti uguali all’estremo più prossimo. quota(quota > 100) = 100; quota(quota < 1) = 1; Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 27 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Funzione quotaCostante() Questa funzione ha il compito di ricercare all’interno del vettore i periodi in cui il titolo si è mantenuto costante e la lunghezza di tali periodi. Definisco la funzione ed inizializzo le variabili che utilizzerò nella funzione. function [valori periodo] = quotaCostante(quota) valori = 0; periodo = 0; giorni = 0; k = 1; costante = 0; L’inizializzazione di valori e periodo serve nel caso in cui il titolo non si sia mai mantenuto costante nel corso dell’anno. Le altre inizializzazioni riguardano variabili utilizzare all’interno della funzione. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 28 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Funzione quotaCostante() for i = 1:length(quota)-1 Analizzo tutti i valori all’interno del vettore if(quota(i+1)==quota(i)) Se due valori consecutivi sono uguali costante = 1; segnalo la presenza di una zona costante, giorni = giorni + 1; incremento il contatore dei giorni. valori(k) = quota(i); Assegno alle variabili di uscita il valore della quota che si periodo(k) = giorni + 1; sta mantenendo costante ed il suo periodo di permanenza elseif(costante == 1) Se non mi trovo in una zona costante ma l’ho appena superata resetto i giorni di permanenza e giorni = 0; costante = 0; segnalo l’assenza di una zona costante k = k + 1; incremento il contatore che tiene traccia delle quote costanti per end prepararmi alla memorizzazione della prossima quota costante. end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 29 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 3 - Codice completo % Script principale quotaX = inizializzaQuotazioni(); [quotaXmax.valore quotaXmax.giorno] = max(quotaX); disp(' ') disp(['Quota massima raggiunta: ' num2str(quotaXmax.valore)]); disp(['nel giorno: ' num2str(quotaXmax.giorno)]); [valore giorni] = quotaCostante(quotaX); disp(' ') disp(['Quote periodiche: ' num2str(valore)]); disp(['di giorni: ' num2str(giorni)]); function quota = inizializzaQuotazioni() quota = input('inserire il vettore delle quotazioni: '); while(length(quota) ~= 365) disp(['Sono stati inseriti' num2str(length(quota)) ' valori. Inserire 365 valori']) disp(' ') quota = input('inserire il vettore delle quotazioni: '); end quota(quota > 100) = 100; quota(quota < 1) = 1; Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 30 Esercizio 3 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 3 - Codice completo function [valori periodo] = quotaCostante(quota) valori = 0; periodo = 0; giorni = 0; k = 1; costante = 0; for i = 1:length(quota)-1 if(quota(i+1)==quota(i)) costante = 1; giorni = giorni + 1; valori(k) = quota(i); periodo(k) = giorni + 1; elseif(costante == 1) giorni = 0; costante = 0; k = k + 1; end end Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 31 Esercizio 4 Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Definire le seguenti funzioni usando due variabili funzionali: f1 = x2 − y 2 !√ " sin x2 +y 2 - f2 = √ 2 2 - x +y -Rappresentare ogni singola funzione con un grafico tridimensionale valutandola per valori di x ed y rispettivamente pari a: x = [-7:0.1:7] e y = [-7:0.1:7]. -Disegnare la porzione di f1 valutata su y = [0:0.1:7] in bianco e quella valutata su y = [0:-0.1:-7] in blu. -Evidenziare nel grafico di f2 i valori ‘discreti’ di cui è composta la funzione per x = [-7:7] e y = [-7:7] Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 32 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Definisco la variabile f1 come variabile funzionale, assegnandole la funzione specificata nella traccia. f1=@(x,y)(x.^2-y.^2); Le variabili funzionali sono funzioni vere e proprie che hanno il vantaggio di poter essere passate ad altre funzioni come parametro. Per definire una variabile f come variabile funzionale, la sintassi è la seguente: f = @(lista_argomenti) funzione Con le variabili funzionali, la definizione di funzione si avvicina ancora di più alla sua accezione matematica rispetto alle funzioni viste fino ad ora. La nostra funzione f1, infatti, può essere valutata per qualsiasi valore di x e y nello stesso modo in cui lo si fa per le funzioni matematiche. f1 valutata in x=3 e y=4: Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione f1(3, 4) Informatica B - Esercitazione 10 del 10/12/2010 33 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Creo l’insieme di valori in cui voglio valutare la parte ‘bianca’ della funzione. x = [0:0.1:7]; y = [0:0.1:7]; [xx,yy]=meshgrid(x,y); I vettori x ed y specificati nella traccia indicano l’intervallo di valori in cui valutare la funzione ma non forniscono tutti i valori necessari a farlo. zz Se valutassimo f1 in x ed y semplicemente con l’istruzione: zz = f1(x, y), otterremmo tutti i valori che essa assume solamente lungo gli assi coordinati. Quello che si vuole ottenere, invece, è valutare la funzione in tutti i punti del piano compresi tra i due assi. Per farlo abbiamo bisogno di generare una ‘griglia’ di valori su cui valutare la funzione. Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione x y Informatica B - Esercitazione 10 del 10/12/2010 34 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 La funzione meshgrid(x,y) genera due matrici. La prima contiene il vettore x replicato tante volte quanti sono i valori in y. La seconda opera analogamente su y. L’insieme delle due matrici è la griglia desiderata. Esempio zz x= [1:5]; y = [5:8]; [xx, yy] = meshgrid(x, y) meshgrid(x,y) x y Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione xx = 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 yy = 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 Informatica B - Esercitazione 10 del 10/12/2010 35 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Valuto f1 in ogni punto della griglia e disegno il risultato. zz=f1(xx,yy); figure(1) mesh(xx,yy,zz); Per disegnare superfici tridimensionali utilizzo la funzione mesh a cui passo le due matrici ottenute da meshgrid ed i relativi valori della funzione. L’istruzione figure(1) crea una nuova finestra d’immagine e le assegna l’identificativo 1. Proseguo il disegno di f1 per i valori della parte in blu, rivaluto la funzione ed aggiungo la nuova porzione alla precedente (senza sovrascrivere). [xx1,yy1]=meshgrid(x,[0:-0.1:-7]); zz1=f(xx1,yy1); figure(1), hold on mesh(xx1,yy1,zz1,'FaceColor','b'); hold off Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 36 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Definisco la funzione f2 e la valuto nel range di valori desiderato disegnandola su di una nuova figura che identifico con il numero 2. f2=@(x,y)(sin(sqrt(x.^2+y.^2))./(sqrt(x.^2+y.^2))) [xx,yy]=meshgrid([-7:0.1:7],[-7:0.1:7]); zz=f2(xx,yy); figure(2) surf(xx,yy,zz); Rivaluto la griglia per rappresentare i valori discreti di f2. Ricalcolo la funzione per i valori scelti e sovrappongo il nuovo grafico a quello esistente. [xx,yy]=meshgrid([-7:7],[-7:7]); zz=f2(xx,yy); figure(2) hold on plot3(xx,yy,zz,'ro', 'Linewidth', 2) hold off Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 37 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 La funzione plot3() funziona analogamente a plot() ma è in grado di rappresentare punti e curve nello spazio tridimensionale. Come plot(), anche plot3() accetta informazioni di visualizzazione come: larghezza del tratto (Linewidth), color e forma del marker (ro), etc. plot3(xx,yy,zz,'ro', 'Linewidth', 2) f1 Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione f2 Informatica B - Esercitazione 10 del 10/12/2010 38 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 In Octave i risultati grafici sono leggermente differenti dato che: ‣mesh() valuta come parametri in ingresso solamente xx, yy, zz ma non 'FaceColor','b'. ‣in plot3() al carattere ‘o’ corrispondono dei triangoli e non dei cerchi. f1 Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione f2 Informatica B - Esercitazione 10 del 10/12/2010 39 Esercizio 4 - Soluzione Salvo Daniele Valente Dipartimento di Elettronica e Informazione MATLAB/Octave - Esercitazione 3 Esercizio 4 - Codice completo f1=@(x,y)(x.^2-y.^2); [xx,yy]=meshgrid([0:0.1:7],[0:0.1:7]); zz=f1(xx,yy); figure(1) mesh(xx,yy,zz); [xx1,yy1]=meshgrid([0:0.1:7],[0:-0.1:-7]); zz1=f1(xx1,yy1); figure(1) hold on mesh(xx1,yy1,zz1,'FaceColor','b'); hold off f2=@(x,y)(sin(sqrt(x.^2+y.^2))./(sqrt(x.^2+y.^2))) [xx,yy]=meshgrid([-7:0.1:7],[-7:0.1:7]); zz=f2(xx,yy); figure(2) surf(xx,yy,zz); [xx,yy]=meshgrid([-7:7],[-7:7]); zz=f2(xx,yy); figure(2) hold on plot3(xx,yy,zz,'ro', 'Linewidth', 2) hold off Politecnico di Milano - DEI Dipartimento di Elettronica e Informazione Informatica B - Esercitazione 10 del 10/12/2010 40