Istruzioni if-else innestate in MATLAB

Concludiamo la nostra trattazione delle istruzioni condizionali if in MATLAB parlando delle istruzioni if-else innestate e della clausola elseif.

In questa lezione vedremo come annidare le istruzioni if-else per controllare più condizioni in modo sequenziale. Vedremo, inoltre, come utilizzare la clausola elseif per semplificare la scrittura di istruzioni condizionali con più condizioni.

Scegliere tra più condizioni

Nelle lezioni precedenti abbiamo visto le istruzioni condizionali if e if-else. La prrima permette di eseguire una serie di istruzioni in base al fatto che una condizione sia vera. La seconda permette di eseguire un blocco di codice se la condizione è vera, e un altro blocco di codice se la condizione è falsa.

Potrebbero sorgere situazioni in cui si voglia scegliere tra più condizioni. Ad esempio, potremmo voler creare una funzione definita a tratti. Supponiamo di voler scrivere una funzione matlab che calcoli la seguente funzione matematica definita a tratti:

f(x) = \begin{cases} 2x + 1 & \text{se } x < 0 \\ x^2 + 1 & \text{se } x \geq 0 \text{ e } x < 1 \\ 3x - 1 & \text{se } x \geq 1 \end{cases}

In questo caso abbiamo più di una condizione da esaminare. Per risolvere questo problema un primo approccio è quello di innestare istruzioni if-else. In altre parole, all'interno di uno dei rami di un'istruzione if-else ne possiamo includere altre.

Volendo realizzare la funzione di sopra possiamo scrivere il codice in questo modo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function y = funzione_definita_a_tratti(x)
    if x < 0
        y = 2*x + 1;
    else
        if x < 1
            y = x^2 + 1;
        else
            y = 3*x - 1;
        end
    end
end

Esaminiamo il codice di sopra. La funzione funzione_definita_a_tratti è composta da un'istruzione if-else che controlla la condizione x < 0. Se questa condizione è rispettata, viene restituito il valore 2*x + 1 rispettando, così, la definizione della funzione matematica di sopra.

Se la condizione è falsa, invece, il blocco di istruzioni che compone il ramo else è composto, a sua volta, da un'altra istruzione if-else. Questa istruzione controlla la condizione x < 1.

Può sembrar strano che l'istruzione controlli solo x < 1. Ci si aspetterebbe che la condizione fosse x >= 0 && x < 1. Tuttavia, in questo caso, la condizione x < 0 è già stata controllata nel ramo precedente. Pertanto, se il controllo arriva al secondo if-else, significa che x >= 0.

Se la condizione x < 1 è rispettata, viene restituito il valore x^2 + 1. Se la condizione è falsa, viene restituito il valore 3*x - 1.

Abbiamo, in questo modo, rispettato tutti i casi della funzione matematica definita a tratti.

Provando ad eseguire la funzione funzione_definita_a_tratti con diversi valori di x otteniamo:

>> funzione_definita_a_tratti(-1)
ans =
     -1
>> funzione_definita_a_tratti(0)
ans =
      1
>> funzione_definita_a_tratti(1)
ans =
      2
>> funzione_definita_a_tratti(2)
ans =
      5

Come possiamo vedere, la funzione restituisce i valori corretti in base al valore di x passato come argomento.

Quello che ci mostra questo esempio è che le istruzioni if-else possono essere annidate.

Definizione

Istruzioni condizionali annidate in MATLAB

Le istruzioni condizionali in MATLAB possono essere annidate. In altre parole, all'interno di uno dei rami di un'istruzione if-else ne possiamo includere altre. Questo permette di controllare più condizioni in modo sequenziale.

Clausola elseif

Sebbene le istruzioni condizionali annidate siano una soluzione valida da impiegare quando si hanno più condizioni da controllare, se queste ultime iniziano a diventare numerose, il codice può diventare difficile da leggere e da manutenere.

Ad esempio, se le condizioni diventano molte, il codice potrebbe diventare illeggibile. Pertanto, MATLAB mette a disposizione la clausola elseif che permette di semplificare la scrittura di istruzioni condizionali con più condizioni.

La struttura generale di un'istruzione condizionale con clausola elseif è la seguente:

if condizione_1
    istruzioni_caso_1
elseif condizione_2
    istruzioni_caso_2
elseif condizione_3
    istruzioni_caso_3
    ...
else
    istruzioni_caso_falso
end

Quando MATLAB incontra un'istruzione condizionale di questo tipo, valuta la condizione condizione_1. Se questa è vera, esegue il blocco di istruzioni istruzioni_caso_1. Se la condizione è falsa, valuta la condizione condizione_2. Se questa è vera, esegue il blocco di istruzioni istruzioni_caso_2. E così via.

Pertanto, possiamo riscrivere il codice della funzione definita a tratti in questo modo:

function y = funzione_definita_a_tratti(x)
    if x < 0
        y = 2*x + 1;
    elseif x < 1
        y = x^2 + 1;
    else
        y = 3*x - 1;
    end
end

Come si può notare, il codice è diventato più leggibile. Inoltre, se volessimo aggiungere un altro caso, possiamo farlo semplicemente aggiungendo un'altra clausola elseif.

Definizione

Clausola elseif in MATLAB

La clausola elseif può essere aggiunta a un'istruzione condizionale if-else per controllare più condizioni in modo sequenziale. La struttura generale è la seguente:

if condizione_1
    istruzioni_caso_1
elseif condizione_2
    istruzioni_caso_2
elseif condizione_3
    istruzioni_caso_3
    ...
else
    istruzioni_caso_falso
end

Esempio: Soluzione di un'equazione di secondo grado

Proviamo ad utilizzare le istruzioni condizionali con clausola elseif per realizzare uno script che risolve un'equazione di secondo grado. L'equazione di secondo grado è della forma:

ax^2 + bx + c = 0

Un'equazione di secondo grado può avere due soluzioni reali, una soluzione reale o nessuna soluzione reale. Le soluzioni sono date dalla formula di Bhaskara:

x = \frac{-b \pm \sqrt{\Delta}}{2a}

dove \Delta = b^2 - 4ac è il discriminante dell'equazione.

Se \Delta &gt; 0, l'equazione ha due soluzioni reali distinte. Se \Delta = 0, l'equazione ha una soluzione reale doppia. Se \Delta &lt; 0, l'equazione non ha soluzioni reali.

Il nostro script sarà, quindi, organizzato come segue:

  1. Chiedere all'utente di inserire i coefficienti a, b e c dell'equazione;
  2. Calcolare il discriminante \Delta;
  3. Utilizzare l'istruzione if per controllare il valore di \Delta e calcolare le soluzioni dell'equazione.

Sfruttando la clausola else-if possiamo scrivere il codice dello script equazione_grado_2.m in questo modo:

% Chiediamo all'utente di inserire i coefficienti dell'equazione
a = input('Inserisci il coefficiente a: ');
b = input('Inserisci il coefficiente b: ');
c = input('Inserisci il coefficiente c: ');

% Calcoliamo il discriminante
delta = b^2 - 4*a*c;

% Calcoliamo le soluzioni dell'equazione
if delta > 0
    x1 = (-b + sqrt(delta)) / (2*a);
    x2 = (-b - sqrt(delta)) / (2*a);
    fprintf('Due soluzioni reali distinte\n');
    fprintf('x1 = %.2f, x2 = %.2f\n', x1, x2);
elseif delta == 0
    x = -b / (2*a);
    fprintf('Una soluzione reale doppia\n');
    fprintf('x = %.2f\n', x);
else
    fprintf('Nessuna soluzione reale\n');
end

Proviamo ad eseguire lo script con diversi valori dei coefficienti a, b e c:

>> equazione_grado_2
Inserisci il coefficiente a: 1
Inserisci il coefficiente b: -3
Inserisci il coefficiente c: 2
Due soluzioni reali distinte
x1 = 2.00, x2 = 1.00
>> equazione_grado_2
Inserisci il coefficiente a: 1
Inserisci il coefficiente b: -2
Inserisci il coefficiente c: 1
Una soluzione reale doppia
x = 1.00
>> equazione_grado_2
Inserisci il coefficiente a: 1
Inserisci il coefficiente b: 2
Inserisci il coefficiente c: 2
Nessuna soluzione reale

Esempio: Controllo del tipo di input

Proviamo a realizzare una funzione che, preso in ingresso una variabile, determini se questa è uno scalare, ossia un numero singolo, un vettore riga, un vettore colonna o una matrice.

Per fare ciò, possiamo utilizzare la funzione size di MATLAB. Questa funzione restituisce le dimensioni di una variabile. Se la variabile è uno scalare, size restituirà [1, 1]. Se la variabile è un vettore riga, restituirà [1, n]. Se la variabile è un vettore colonna, restituirà [m, 1]. Se la variabile è una matrice, restituirà [m, n].

Per implementare questa funzione possiamo adoperare la clausola elseif:

function tipo = controlla_tipo(variabile)
    dimensioni = size(variabile);

    if dimensioni(1) == 1 && dimensioni(2) == 1
        tipo = 'Scalare';
    elseif dimensioni(1) == 1
        tipo = 'Vettore riga';
    elseif dimensioni(2) == 1
        tipo = 'Vettore colonna';
    else
        tipo = 'Matrice';
    end
end

Proviamo ad eseguire la funzione controlla_tipo con diversi tipi di variabili:

>> controlla_tipo(5)
ans =
    'Scalare'
>> controlla_tipo([1, 2, 3])
ans =
    'Vettore riga'
>> controlla_tipo([1; 2; 3])
ans =
    'Vettore colonna'
>> controlla_tipo([1, 2; 3, 4])
ans =
    'Matrice'

Come possiamo vedere, la funzione controlla_tipo restituisce il tipo corretto della variabile passata come argomento.

Ordine di valutazione delle clausole elseif

Quando MATLAB incontra un'istruzione condizionale con più clausole elseif, valuta le condizioni nell'ordine in cui sono scritte. La prima condizione che risulta vera determina l'esecuzione del blocco di istruzioni corrispondente. Le clausole successive non vengono valutate.

Pertanto, bisogna prestare la massima attenzione all'ordine in cui le clausole elseif sono scritte. Se una condizione è più generale di un'altra, questa deve essere scritta per ultima.

Ad esempio, consideriamo il seguente codice:

function controlla_x(x)
    if x < 0
        disp('x è negativo');
    elseif x < 10
        disp('x è minore di 10');
    else
        disp('x è maggiore o uguale a 10');
    end
end

Il codice di sopra funziona correttamente perché la condizione x < 0 è più specifica della condizione x < 10. Detto in altri termini, l'insieme dei numeri minori di dieci include anche i numeri negativi.

Provando ad eseguire il codice con diversi valori di x otteniamo:

>> x = -5;
>> controlla_x(x)
x è negativo
>> x = 5;
>> controlla_x(x)
x è minore di 10
>> x = 15;
>> controlla_x(x)
x è maggiore o uguale a 10

Tuttavia, se invertiamo l'ordine delle clausole elseif, il codice non funzionerà correttamente:

if x < 10
    disp('x è minore di 10');
elseif x < 0
    disp('x è negativo');
else
    disp('x è maggiore o uguale a 10');
end

Provando ad eseguire il codice con gli stessi valori di x otteniamo:

>> x = -5;
>> controlla_x(x)
x è minore di 10
>> x = 5;
>> controlla_x(x)
x è minore di 10
>> x = 15;
>> controlla_x(x)
x è minore di 10

Come possiamo vedere, il codice non funziona correttamente. Questo perché la condizione x < 10 è più generale della condizione x < 0. Pertanto, quando x è negativo, la condizione x < 10 risulta vera e viene eseguito il blocco di istruzioni corrispondente. La condizione x < 0 non viene mai valutata.

Nota

Ordine delle clausole elseif

Quando si scrivono istruzioni condizionali con più clausole elseif, bisogna prestare attenzione all'ordine in cui le clausole sono scritte. Le condizioni più specifiche devono essere scritte per prime, mentre le condizioni più generali devono essere scritte per ultime.

Questo perché MATLAB valuta le condizioni nell'ordine in cui sono scritte. La prima condizione che risulta vera determina l'esecuzione del blocco di istruzioni corrispondente. Le clausole successive non vengono valutate.

In Sintesi

In questa lezione abbiamo visto come utilizzare le istruzioni condizionali if-else innestate in MATLAB per controllare il flusso di esecuzione del codice. Abbiamo visto che le istruzioni condizionali possono essere annidate, ossia all'interno di uno dei rami di un'istruzione if-else ne possiamo includere altre.

Abbiamo, inoltre, introdotto la clausola elseif che permette di semplificare la scrittura di istruzioni condizionali con più condizioni. Abbiamo visto che MATLAB valuta le condizioni nell'ordine in cui sono scritte e che, pertanto, bisogna prestare attenzione all'ordine in cui le clausole elseif sono scritte.

Infine, abbiamo visto come utilizzare le istruzioni condizionali con clausola elseif per realizzare uno script che risolve un'equazione di secondo grado e una funzione che determina il tipo di una variabile.

Nella prossima lezione, studieremo un altro tipo di istruzioni condizionali: le istruzioni switch-case.