Main Content

Flusso di controllo

Controllo condizionale: if, else, switch

Le dichiarazioni condizionali consentono di selezionare, durante l'esecuzione, i blocchi di codici da eseguire. La dichiarazione condizionale più semplice è una dichiarazione if. Ad esempio:

% Generate a random number
a = randi(100, 1);

% If it is even, divide by 2
if rem(a, 2) == 0
    disp('a is even')
    b = a/2;
end

Le dichiarazioni if possono includere scelte alternative, tramite le parole chiave opzionali elseif o else. Ad esempio:

a = randi(100, 1);

if a < 30
    disp('small')
elseif a < 80
    disp('medium')
else
    disp('large')
end

In alternativa, per effettuare il test dell'uguaglianza rispetto a una serie di valori noti, utilizzare una dichiarazione switch. Ad esempio:

[dayNum, dayString] = weekday(date, 'long', 'en_US');

switch dayString
   case 'Monday'
      disp('Start of the work week')
   case 'Tuesday'
      disp('Day 2')
   case 'Wednesday'
      disp('Day 3')
   case 'Thursday'
      disp('Day 4')
   case 'Friday'
      disp('Last day of the work week')
   otherwise
      disp('Weekend!')
end

MATLAB®, sia per if che per switch, esegue il codice corrispondente alla prima condizione vera, quindi esce dal blocco di codice. Ogni dichiarazione condizionale richiede la parola chiave end.

In generale, in caso di numerosi possibili valori discreti noti, risulta più semplice leggere le dichiarazioni switch rispetto a if. Non è tuttavia possibile effettuare test di disuguaglianza tra i valori di switch e di case. Ad esempio, non è possibile implementare questo tipo di condizione con una dichiarazione switch:

yourNumber = input('Enter a number: ');

if yourNumber < 0
    disp('Negative')
elseif yourNumber > 0
    disp('Positive')
else
    disp('Zero')
end

Confronto tra array nelle dichiarazioni condizionali

È importante comprendere il funzionamento degli operatori relazionali e delle dichiarazioni if con le matrici. Per verificare l'uguaglianza tra due variabili è possibile utilizzare

if A == B, ...

Si tratta di codice di MATLAB valido, che funziona come previsto quando A e B sono scalari. Ma quando A e B sono matrici, A == B non testa se sono uguali, ma dove sono uguali; il risultato è un'altra matrice di 0 e 1 che dimostra l'uguaglianza di ogni singolo elemento.

A = magic(4);
B = A;
B(1,1) = 0;

A == B

ans =

  4×4 logical array

   0   1   1   1
   1   1   1   1
   1   1   1   1
   1   1   1   1

Il metodo appropriato per verificare l'uguaglianza tra due variabili consiste nell'utilizzare la funzione isequal:

if isequal(A, B), ...

isequal restituisce un valore logico scalare di 1 (che significa true) o 0 (false), invece di una matrice, come espressione da valutare tramite la funzione if. Utilizzando le matrici A e B sopra riportate, si ottiene

isequal(A,B)

ans =

  logical

   0

Ecco un altro esempio per sottolineare questo punto. Se A e B sono scalari, il programma seguente non raggiungerà mai la "situazione non prevista". Per la maggior parte delle matrici, inclusi i nostri quadrati magici con colonne scambiate, tuttavia, nessuna delle condizioni di matrice A > B, A < B o A == B risulta vera per tutti gli elementi, quindi viene eseguita la clausola else:

if A > B
   'greater'
elseif A < B
   'less'
elseif A == B
   'equal'
else
   error('Unexpected situation')
end

Diverse funzioni sono utili per ridurre i risultati dei confronti di matrici a condizioni scalari, da utilizzare con if, incluso

isequal
isempty
all
any

Controllo sui loop: for, while, continue, break

Questa sezione illustra le funzioni di MATLAB che offrono un controllo sui loop nei programmi.

for

Il loop for ripete un gruppo di dichiarazioni per un numero fisso e predeterminato di volte. Le dichiarazioni sono delimitate da un end corrispondente:

for n = 3:32
   r(n) = rank(magic(n));
end
r

Il punto e virgola che conclude la dichiarazione interna sopprime la ripetizione della stampa, mentre l'elemento r dopo il loop visualizza il risultato finale.

È buona prassi far rientrare i loop per una maggior leggibilità, in particolare quando sono annidati:

for i = 1:m
   for j = 1:n
      H(i,j) = 1/(i+j);
   end
end

while

Il loop while ripete un gruppo di dichiarazioni per un numero indefinito di volte sotto il controllo di una condizione logica. Le dichiarazioni sono delimitate da un end corrispondente.

Qui di seguito viene riportato un programma completo, che illustra l'uso di while, if, else ed end, che cerca lo zero di un polinomio con il metodo della bisezione di un intervallo:

a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
   x = (a+b)/2;
   fx = x^3-2*x-5;
   if sign(fx) == sign(fa)
      a = x; fa = fx;
   else
      b = x; fb = fx;
   end
end
x

Il risultato è la radice del polinomio x3 – 2x – 5, vale a dire

x =
   2.09455148154233

Quanto riportato relativamente ai confronti tra matrici nella sezione sulla dichiarazione if si applica anche alla dichiarazione while.

continue

La dichiarazione continue passa il controllo all'iterazione successiva del loop for o del loop while in cui appare, saltando le restanti dichiarazioni nel corpo del loop. Lo stesso vale per le dichiarazioni continue nei loop annidati. Ciò significa che l'esecuzione continua all'inizio del loop in cui si trova la dichiarazione continue.

L'esempio seguente illustra un loop continue che conta le righe di codice nel file magic.m, saltando tutte le righe vuote e i commenti. Una dichiarazione continue consente di passare alla riga successiva in magic.m senza incrementare il conteggio ogni volta che viene rilevata una riga vuota o una riga di commento:

fid = fopen('magic.m','r');
count = 0;
while ~feof(fid)
    line = fgetl(fid);
    if isempty(line) || strncmp(line,'%',1) || ~ischar(line)
        continue
    end
    count = count + 1;
end
fprintf('%d lines\n',count);
fclose(fid);

break

La dichiarazione break consente di uscire anticipatamente da un loop for o da un loop while. Nei loop annidati, break esce solo dal loop più interno.

Ecco un miglioramento dell'esempio della sezione precedente. Perché è una buona idea usare break in questo modo?

a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
   x = (a+b)/2;
   fx = x^3-2*x-5;
   if fx == 0
      break
   elseif sign(fx) == sign(fa)
      a = x; fa = fx;
   else
      b = x; fb = fx;
   end
end
x

Termine del programma: return

Questa sezione illustra la funzione MATLAB return che consente di terminare il programma prima del completamento dell'esecuzione.

return

return termina la sequenza corrente di comandi e restituisce il controllo alla funzione invocante o alla tastiera. return è utilizzato anche per terminare la modalità keyboard. Una funzione invocata solitamente trasferisce il controllo alla funzione che l'ha invocata quando raggiunge la fine della funzione. È possibile inserire una dichiarazione return all'interno della funzione invocata per terminarla anticipatamente e trasferire il controllo alla funzione invocante.

Vettorializzazione

Un metodo per velocizzare l'esecuzione dei programmi di MATLAB consiste nel vettorializzare gli algoritmi utilizzati nella realizzazione del programma. Nei casi in cui altri programmi potrebbero utilizzare i loop for o DO, MATLAB è in grado di utilizzare operazioni su vettori o matrici. Un semplice esempio richiede la creazione di una tabella di logaritmi:

x = 0.01;
y = log10(x);
for k = 1:999
  x(k+1) = x(k) + 0.01;
  y(k+1) = log10(x(k+1));
end

Una versione vettorializzata dello stesso codice è

x = .01:.01:10;
y = log10(x);

In caso di codice più complesso, le opzioni di vettorializzazione non sono sempre così ovvie.

Pre-allocazione

Se non fosse possibile vettorializzare una parte di codice, velocizzare l'esecuzione dei loop for pre-allocando qualsiasi vettore o array in cui vengono memorizzati i risultati dell'output. Ad esempio, questo codice utilizza la funzione zeros per pre-allocare il vettore creato nel loop for. Questo velocizza notevolmente l'esecuzione del loop for:

r = zeros(32,1);
for n = 1:32
    r(n) = rank(magic(n));
end

Senza la preallocazione dell'esempio precedente, l'interprete di MATLAB aumenta il vettore r un elemento alla volta per tutto il loop. La pre-allocazione del vettore elimina questa fase e consente di velocizzare l'esecuzione.