Sei sulla pagina 1di 8

Laboratorio 3

Cicli e script.
2014 - Questo testo (compresi i quesiti ed il loro svolgimento) `
e coperto da diritto dautore. Non pu`
o di pubblicazione editoriale. Non possono essere ricavati lavori derivati. Ogni abuso sar`
o essere sfruttato a fini commerciali
a punito a termine di legge dal titolare del diritto.
This text is licensed to the public under the Creative Commons Attribution-NonCommercial-NoDerivs2.5 License
(http://creativecommons.org/licenses/by-nc-nd/2.5/)

Nel primo laboratorio `e stato introdotto il quadrato magico come esempio di matrice:

16 2 3 13
5 11 10 8

A= .
9 7 6 12
4 14 15 1
Tra le varie domande dellesercizio proposto, era stato chiesto di sommare gli elementi dellantidiagonale
(elementi nei riquadri). Ad esempio `e possibile scrivere:

>> A( 1, 4 ) + A( 2, 3 ) + A( 3, 2 ) + A( 4, 1 )
ans =
34

oppure

>> sum( [ A( 1, 4 ), A( 2, 3 ), A( 3, 2 ), A( 4, 1 ) ] )
ans =
34.

Le soluzioni proposte sopra non sono ovviamente adatte a calcolare la somma degli elementi
sullantidiagonale nel caso di matrici di grandi dimensioni (si pensi ad esmpio ad una matrice
di dimensioni 1000 1000!). Per ovviare a questa limitazione, sarebbe utile disporre di un
modo automatico per scandire tutti gli elementi dellantidiagonale uno per uno. Le operazioni
da compiere sono semplici e ripetitive: partendo dal primo elemento dellantidiagonale:

1. memorizzare lelemento estratto dalla matrice come elemento di un vettore che contenga
lantidiagonale

2. se lelemento considerato non `e lultimo, passare al successivo e tornare al punto (1)


altrimenti terminare lesecuzione.

Si tratta di un esempio di ciclo, cio`e di una serie di istruzioni da ripetere un numero deter-
minato di volte.

>> n = size( A, 1 )
n =
4
>> for i = 1 : n
ad( i ) = A( i, n-i+1 );
>> end
>> ad
ad =
13 10 7 4

1
>> sum( ad )
ans =
34.

Listruzione for i = 1 : n indica linizio di un ciclo, da eseguire un numero di volte pari


alla lunghezza del vettore 1:n. Ogni volta la variabile i assumer`a un valore differente, prima
1 poi 2, 3, . . . fino a n. Le istruzioni da ripetere sono racchiuse tra la riga contente for e quella
contenente end. Si noti che la variabile i `e disponibile allinterno del ciclo, con un valore
che `e incrementato ad ogni iterazione. Al termine del ciclo alla variabile i resta assegnato
il valore pari a n, cio`e 4. (Nota: i `e una variabile predefinita in Matlabr ed Octave e
corrisponde allunit` a immaginaria. Con le ultime istruzioni ha per`o assunto un nuovo valore,
dato dal ruolo di iteratore del ciclo. Per riassegnare lunit`a immaginaria ad i si pu`o utilizzare
listruzione clear i oppure i = sqrt(1)).
Si sarebbe potuta effettuare direttamente la somma allinterno del ciclo, tramite somme
parziali:

>> s = 0;
>> for i = 1 : n
s = s + A( i, n-i+1 );
>> end
>> s
s =
34

La scrittura di programmi da linea di comando `e pratica perche immediata ed interattiva,


ma `e comoda solo quando il numero di istruzioni `e limitato. Nel caso si voglia scrivere codice
lungo e soprattutto si voglia avere la possibilt`a di riutilizzare in futuro quanto gi`a scritto,
`e utile salvare i comandi in uno file di script. Matlabr ed Octave utilizzano dei semplici
file di testo non formattato con estensione .m per memorizzare le istruzioni; file di questo
tipo sono detti Mfiles. A questo scopo apriamo leditor di Matlabr o Octave utilizzando
il comando edit. Matlab dispone di un proprio editor, mentre Octave pu`o aprire un editor
presente sistema oppure anchesso un editor dedicato, se si utilizza uninterfaccia grafica come
QtOctave (si rimanda al sito web del corso per i dettagli). Leditor di Matlab o QtOctave
pu`o essere aperto anche cliccando sulla aposita icona nella barra in alto. In realt`a pu`o essere
utilizzato qualsiasi editor che possa salvare testo non formattato: ne esistono tantissimi e molti
sanno riconoscere la sintassi di Matlabr e Octave. Dopo aver aperto leditor, si scrivono i
comandi come se fossero nel prompt dei comandi:

Listing 1: Script antidiag.m


n = s i z e ( A, 1 ) ;
for i = 1 : n
ad ( i ) = A( i , ni +1 ) ;
end
sum ( ad )
Salviamo il file con il nome antidiag.m. Si possono eseguire i comandi contenuti nel file
scrivendo semplicemente il nome del file dalla riga di comando, se il file si trova nella cartella

2
in cui stiamo lavorando, oppure run . . . /antidiag.m, dove . . . indicano il percorso dalla
cartella dove stiamo lavorando alla cartella in cui il file `e salvato.
` possibile cambiare la directory di lavoro utilizzando il comando cd (si digiti help cd per
E
maggiori chiarimenti) oppure tramite lapposita casella disponibile nellinterfaccia grafica (sia
per Matlab che per QtOctave).

>> antidiag
ans =
34

Le variabili utilizzate durante lesecuzione dellMfile vengono assegnate nello spazio di lavoro,
come se le istruzioni fossero state battute nel prompt dei comandi.

Esercizio 1
1. Scrivere uno script mat hilbert.m che fornisca la matrice di Hilbert avente dimensione
5 5, i cui elementi ai j sono definiti da:

1
ai j =
i+j1

. (SUGGERIMENTO: utilizzare due cicli for annidati.)

2. Verificare il corretto funzionamento della funzione del punto precedente, confrontandone


il risultato con la matrice restituita dal comando hilb(5).

Non sempre `e noto in anticipo il numero di iterazione da compiere nel ciclo: a volte la
condizione di uscita si determina nel ciclo stesso e non `e possibile prevedere a priori quando sia
verificata. In questi casi il ciclo for non `e adatto, ma si pu`o utilizzare il ciclo while. Abbiamo
visto che la funzione eps(n) si comporta diversamente in Octave e Matlab: in particolare
in Matlab permette di calcolare lepsilon macchina rispetto ad un numero qualsiasi n, non
necessariamente 1. Vogliamo scrivere un programma che riproduca il comportamento di
eps(n) di Matlab, cos` che sia possibile scrivere una funzione analoga in Octave (la vedremo
dopo aver introdotto le funzioni nel prossimo laboratorio). Nel file epsilon.m scriviamo uno
script che calcoli lepsilon macchina di 1000:

Listing 2: Script eps script.m


n =1000;
e p s i l o n = 2 f l o o r ( l o g 2 ( n ) ) ;

w h i l e ( ( n+e p s i l o n ) > n )
e p s i l o n = e p s i l o n /2;
end

e p s i l o n = e p s i l o n *2
Proviamo ad eseguire lo script ed a verificare il risultato con eps di Matlab:

3
>> eps_script

epsilon =

1.1369e-13

>> eps(1000)

ans =

1.1369e-13

Ad ogni iterazione lespressione (n+epsilon) > n `e valutata ed il ciclo prosegue solo nel
caso sia vera. Si noti che `e valutata anche in concomitanza del primo ingresso nel ciclo: nel
caso sia gi`
a vera, non sar`a effettuata alcuna iterazione e lesecuzione proseguir`a con la prima
istruzione dopo end.
Al posto dellutilizzo di while, a volte si scrive un ciclo for con un numero di iterazioni
sufficientemente alto e si permette unuscita anticipata tramite listruzione break. Si tratta
di una pessima prassi di programmazione, infatti in un ciclo deve essere chiaramente visibile
quale sia la condizione di uscita, indicata allinizio o al termine del ciclo stesso (dipende
dalle istruzioni utilizzate e dai lunguaggi). Inserire condizioni di uscita alternative tramite
break sparsi nel codice, specialmente nel caso di codice complesso, significa offuscare il
comportamento dellalgoritmo e rendere difficile lindividuazione di eventuali errori.
Dopo lesecuzione dello script, lespressione (n+epsilon) > n `e sicuramente verificata.
Proviamo ad inserirla nel prompt dei comandi:

>> (n+epsilon) > n

ans =

>> (n+epsilon) < n

ans =

come si vede Matlab ed Octave attribuiscono un risultato numerico 1 ad unespressione va-


lutata come vera e 0 ad una espressione valutata come falsa. Questo comportamento, che
sembra molto naturale a chi conosca un minimo di logica Booleana e di programamzione, non
`e per nulla banale nel caso siano coinvolte matrici come vedremo tra poco.
while non `e lunica istruzione di Matlab che permetta una valutazione di una espressione,
infatti `e possibile eseguire delle istruzioni al verificarsi di determinate condizioni tramite il
comando if:

>> if (5>3)
disp(5 e maggiore di 3)

4
end
5 e maggiore di 3
>> if (5<3)
disp(5 e minore di 3)
end
>> if (5==3)
disp(5 e uguale a 3)
end
>> if (5~=3)
disp(5 e diverso da 3)
end
5 e diverso da 3
` possibile anche indicare unalternativa tramite else:
E

if (5<3)
disp(5 e minore di 3)
else
disp(5 e maggiore o uguale a 3)
end
5 e maggiore o uguale a 3
` possibile concatenare pi`
E u if con condizioni alternative tramite elseif:

>> if (5<3)
disp(5 e minore o uguale a 3)
elesif (5==3)
disp(5 e uguale a 3)
else
disp(5 e maggiore di 3)
end
5 e maggiore di 3

Proviamo a valutare alcune espressioni, il cui risultato `e vero o falso nel caso di matrici:

>> A=ones(3)

A =

1 1 1
1 1 1
1 1 1

>> B=2*A

B =

2 2 2
2 2 2

5
2 2 2

>> B>A

ans =

1 1 1
1 1 1
1 1 1

>> B<A

ans =

0 0 0
0 0 0
0 0 0

>> B==A

ans =

0 0 0
0 0 0
0 0 0

>> B~=A

ans =

1 1 1
1 1 1
1 1 1

>> B(1,1)=-5

B =

-5 2 2
2 2 2
2 2 2

>> B>A

ans =

0 1 1

6
1 1 1
1 1 1
Come si vede il risultato `e quello di una valutazione elemento per elemento. Come ci si
aspetta, una matrice di tutti zeri `e interpretata come falso ed una composta da soli numeri
uno come vero. Ma cosa succede con una matrice come lultima? Per Matlab ed Octave sono
vere solo le epressioni che non hanno zeri nella matrice di valutazione; ci`o sembra ragionevole,
ma pu`o portare a risultati inaspettati:
>> if(A==B)
disp(A e uguale a B)
elseif(A~=B)
disp(A e diversa da B)
else
disp(A non e ne uguale ne diversa da B)
end
A non e ne uguale ne diversa da B
Per Matlab ed Octave le matrici A e B non sono ne uguali ne diverse!!
E` inoltre possibile costruire una espressione Booleana, tramite gli operatori logici &&, || ,
. Si sottolinea che &&, || possono essere utilizzati solo con operandi scalari:
>> if ((A<B)||(A==ones(3)))
disp(la matrice A e minore di B oppure e pari a ones(3))
end
??? Operands to the || and && operators must be convertible to logical scalar values.

>> if ((a<b)||(b==0))
disp(a e minore di b oppure b e nullo)
end
a e minore di b oppure b e nullo
Esistono anche i corrispondenti operatori elemento per elemento: & e |
>> (A<B)|(A==ones(3))

ans =

1 1 1
1 1 1
1 1 1

Esercizio 2
Una famoso problema non ancora risolto `e quello della convergenza della successione 3n + 1,
definita come segue: dato n0 intero arbitrario,
se ni `e pari, allora ni+1 = n/2;

se ni `e dispari allora ni+1 = 3n + 1;

7
se ni = 1 la successione termina.

Per esempio, se n0 = 7 la successione `e la seguente: 7, 22, 11, 34, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1.
Chiaramente la successione converge logaritmicamente in n non appena sia ni = 2N , con N
intero positivo o nullo.
Scrivere uno script treuno.m che permetta di scegliere n0 arbitrario e memorizzi la suc-
cessione in un vettore. (SUGGERIMENTO: si pu`o utilizzare la funzione rem. Per maggiori
informazioni: help rem)

Esercizio 3
Utilizzare un ciclo while per determinare quanto tempo occorre per accumulare un milione
di euro in un conto corrente bancario se vengono depositati 10 mila euro iniziali, 10 mila alla
fine di ogni anno e se la banca riconosce un interesse annuo del 2% sui conti correnti.

Esercizio 4
Per il calcolo di si pu`o utilizzare il seguente metodo: si generano n coppie {(xk , yk )} di
numeri casuali compresi tra 0 e 1 e di questi si calcola il numero m di punti che cadono nel
primo quarto del cerchio di centro lorigine e raggio 1. Si ha che pi e il limite per n
dei rapporti n = 4m/n. Si scriva un programma che esegua questo calcolo e si verifichi la
correttezza del risultato al crescere di n. (SUGGERIMENTO: utilizzare la funzione rand.)

Pu`o capitare di dover scegliere tra molte condizioni alternative e mutuamente esclusive.
In questo caso `e utile listruzione switch:

funzione = ' cubica ' ;

switch funzione
case ' l i n e a r e '
disp ( ' la funzione e ' ' lineare ' )
case ' cubica '
disp ( ' la funzione e ' ' cubica ' )
otherwise
d i s p ( ' f u n z i o n e non l i n e a r e ne ' ' c u b i c a ' )
end
i singoli casi sono contraddistinti da case, se nessuno di questi si verifica `e possibile indicare
unopzione di riserva con otherwise. A differenza che in altri linguaggi, come C/C++, il
controllo delle condizioni esce alla prima corrispondenza trovata e lesecuzione prosegue dalla
prima istruzione dopo end.

Potrebbero piacerti anche