Ciclo For in MATLAB
In questa lezione approfondiamo l'utilizzo dei cicli for
in MATLAB, uno strumento essenziale per eseguire sequenze di operazioni ripetitive.
Esaminiamo come gestire l'iterazione, l'inizializzazione di variabili e l'implementazione di somme e prodotti progressivi, sfruttando anche le tecniche di preallocazione dei vettori.
Il Ciclo for
Il costrutto for
, o ciclo for
, viene utilizzato quando è necessario ripetere un'istruzione (o più istruzioni) in uno script o in una funzione, e quando si sa in anticipo quante volte tale azione dovrà essere ripetuta.
Le istruzioni ripetute vengono chiamate corpo del ciclo. Ad esempio, potrebbe essere noto che l'azione del ciclo dovrà ripetersi cinque volte. In questo caso, diciamo che iteriamo il corpo del ciclo cinque volte.
La variabile che viene usata per iterare sui valori si chiama variabile di loop o variabile iteratrice.
Ad esempio, tale variabile potrebbe iterare sugli interi da 1 a 5 (ovvero, 1, 2, 3, 4 e poi 5). In generale i nomi di variabile dovrebbero essere significativi, ma è comune in molti linguaggi di programmazione usare nomi come i
(e se serve più di una variabile iteratrice, allora i
, j
, k
, l
e così via).
Questo è legato a motivi storici e al modo in cui le variabili intere erano nominate in Fortran. In MATLAB, però, sia i
sia j
sono funzioni built-in che restituiscono i
come variabile di loop.
La forma generale del ciclo for è:
for variabile = intervallo
istruzioni
end
dove variabile
è la variabile di loop, mentre intervallo
è l'insieme di valori su cui la variabile itererà, e l'azione del loop consiste in tutte le istruzioni fino a end
.
Come con le istruzioni if
, il corpo del loop è indentato per renderlo più leggibile. L'intervallo intervallo
può essere specificato usando qualunque vettore, ma normalmente il modo più semplice per indicare un insieme di valori è usare l'operatore due punti.
Come esempio, stampiamo una colonna di numeri da 1 a 5.
Se si lancia il comando in Command Window, i risultati appariranno dopo il loop:
>> for i = 1:5
fprintf('%d\n', i)
end
Uscita:
1
2
3
4
5
Per prima cosa la variabile i
viene inizializzata al valore 1. Poi si esegue l'azione del loop, che qui è la funzione fprintf
che stampa il valore di i
(1) e poi un carattere di newline per andare a capo.
Successivamente, i
viene incrementato per assumere il valore 2. Si ripete l'azione, che stampa 2 e il newline. Poi i
diventa 3, e così via fino a 5. Il valore finale di i
è 5; tale valore può essere usato una volta che il loop è terminato.
Naturalmente, usare disp
può ottenere lo stesso risultato più velocemente per stampare un vettore in colonna:
>> disp([1:5]')
Uscita:
1
2
3
4
5
Vediamo un altro esempio semplice. Come possiamo stampare questa colonna di interi (usando il metodo di programmazione) se i valori fossero 0, 50, 100, 150, 200?
In un loop, potremmo stampare questi valori a partire da 0, con incremento di 50, fino a 200. Ognuno stampato con una larghezza di campo pari a 3:
>> for i = 0:50:200
fprintf('%3d\n',i)
end
Uscita:
0
50
100
150
200
Cicli For che non usano la variabile iteratrice
Nell'esempio precedente, il valore della variabile di loop è stato usato nel corpo del ciclo (veniva stampato). Non è però sempre necessario usare effettivamente il valore della variabile di loop.
A volte la variabile serve solo per iterare o ripetere un'azione un determinato numero di volte. Per esempio:
for i = 1:3
fprintf('Ciao, come si va?\n')
end
produce in uscita:
Ciao, come si va?
Ciao, come si va?
Ciao, come si va?
La variabile i
serve semplicemente a ripetere tre volte l'azione, anche se il suo valore non viene usato nell'azione del loop.
Analogamente, il loop:
for i = 4:2:8
fprintf('Ciao, come si va?\n')
end
darà esattamente lo stesso risultato. Non importa che i valori assunti da i
siano 4, poi 6, poi 8 invece di 1, 2, 3. Poiché la variabile di loop non è utilizzata nell'azione, si tratta semplicemente di un altro modo di specificare che l'azione deve essere ripetuta tre volte. Naturalmente, usare 1:3
sarebbe più logico.
Proviamo a realizzare un ciclo for
che stampa cinque asterischi in colonna:
>> for i = 1:5
fprintf('*\n')
end
Uscita:
*
*
*
*
*
Funzioni di input e ciclo for
Lo script seguente ripete il processo di chiedere all'utente un numero e di ristamparlo a video.
La variabile di loop specifica quante volte ciò deve accadere. In questo esempio, la variabile di loop non è usata direttamente nell'azione, ma serve solo a stabilire quante volte ripetere l'azione.
Chiamiamo questo script forecho.m
:
% Questo script esegue un ciclo per ripetere l'azione di
% chiedere all'utente un numero e ristamparlo a video
for iv = 1:3
inputnum = input('Inserisci un numero: ');
fprintf('Hai inserito %.1f\n', inputnum)
end
Esempio di esecuzione:
>> forecho
Inserisci un numero: 3.4
Hai inserito 3.4
Inserisci un numero: 2.1
Hai inserito 2.1
Inserisci un numero: 5.6
Hai inserito 5.6
In questo esempio, la variabile iv
itera sui valori 1, 2 e 3, quindi l'azione si ripete tre volte. L'azione consiste nel chiedere all'utente un numero e stamparlo con una cifra decimale.
Calcolare somme e prodotti
Un'applicazione molto comune di un ciclo for
è calcolare somme e prodotti. Per esempio, invece di limitarsi a ristampare i numeri che l'utente inserisce, si potrebbe calcolarne la somma.
Per farlo, occorre aggiungere ciascun valore a una variabile accumulatore. Un accumulatore cambia di continuo, man mano che si aggiungono nuovi numeri. Questa variabile deve essere inizializzata a 0.
Come esempio, scriviamo uno script somma_numeri
che somma i n
numeri inseriti dall'utente; n
è un intero casuale generato dallo script.
Per calcolare la somma, ci occorrono una variabile di loop o iteratore i
, e anche una variabile per memorizzare la somma progressiva. In questo caso, useremo la variabile accumulatore
come somma progressiva. Ogni volta che eseguiamo il loop, il nuovo valore inserito dall'utente viene aggiunto al valore attuale di accumulatore
. Al termine, lo script stampa il risultato finale, ossia la somma di tutti i numeri, memorizzata nella variabile accumulatore
.
% somma_numeri calcola la somma dei n numeri
% inseriti dall'utente
n = randi([3 10]);
accumulatore = 0;
for i = 1:n
inputnum = input('Inserisci un numero: ');
accumulatore = accumulatore + inputnum;
end
fprintf('La somma è %.2f\n', accumulatore)
Se n
fosse 3, lo script calcolerebbe e stamperebbe la somma dei numeri che l'utente inserisce, ad esempio 4 + 3.2 + 1.1 = 8.3.
Un'altra applicazione comune di un ciclo for
è calcolare un prodotto progressivo. In tal caso, la variabile che accumula il prodotto deve essere inizializzata a 1 (invece che a 0, come avviene per la somma progressiva).
A titolo di esempio, scriviamo uno script prodotto_numeri
che calcola il prodotto di n
numeri inseriti dall'utente, dove n
è un intero casuale generato dallo script.
% prodotto_numeri calcola il prodotto dei n numeri
% inseriti dall'utente
n = randi([3 10]);
accumulatore = 1;
for i = 1:n
inputnum = input('Inserisci un numero: ');
accumulatore = accumulatore * inputnum;
end
fprintf('Il prodotto è %.2f\n', accumulatore)
Preallocazione di vettori
Quando i numeri vengono inseriti dall'utente, è spesso necessario memorizzarli in un vettore.
Ci sono due metodi base per farlo. Il primo è partire con un vettore vuoto e aggiungere ogni numero man mano che l'utente lo inserisce.
Tuttavia, estendere un vettore ripetutamente è molto inefficiente. Ogni volta che il vettore si allunga, deve essere trovato in memoria un nuovo blocco (chunk) abbastanza grande per il nuovo vettore, e tutti i valori precedenti devono essere ricopiati dal vettore originale al vettore nuovo. Questo può richiedere tempo.
Un metodo migliore è preallocare il vettore della giusta dimensione e poi sostituire ogni elemento con i valori inseriti dall'utente. Questo metodo prevede di riferirsi a ogni indice del vettore di destinazione e di posizionarvi il numero man mano che viene inserito.
È nettamente superiore, se si sa in anticipo quanti elementi avrà il vettore. Un metodo comune è usare la funzione zeros
per preallocare un vettore della giusta lunghezza.
Ecco uno script che fa esattamente questo e poi stampa il vettore risultante. Lo script genera un intero casuale n
e ripete il processo n
volte. Poiché si sa che il vettore risultante avrà n
elementi, si può preallocare il vettore.
% crea_vettore crea un vettore di lunghezza n
% Chiede all'utente di inserire n numeri in un vettore
n = randi([2 5]);
numvec = zeros(1,n);
for iv = 1:n
inputnum = input('Inserisci un numero: ');
numvec(iv) = inputnum;
end
fprintf('Il vettore è: \n')
disp(numvec)
Esempio di esecuzione:
>> crea_vettore
Inserisci un numero: 3.4
Inserisci un numero: 2.1
Inserisci un numero: 5.6
Il vettore è:
3.4000 2.1000 5.6000
È molto importante notare che la variabile iv
del ciclo viene usata come indice per il vettore.
Esempio: Calcolo della media dei numeri inseriti
Proviamo a scrivere uno script che calcola la media dei numeri inseriti dall'utente. Questo script è simile a quello che calcola la somma dei numeri, ma alla fine calcola la media.
A differenza degli script di sopra, questo script chiede prima all'utente quanti numeri vuole inserire, e poi calcola la media di quei numeri.
% media_numeri calcola la media dei n numeri
% inseriti dall'utente
n = input('Quanti numeri vuoi inserire? ');
accumulatore = 0;
for i = 1:n
inputnum = input('Inserisci un numero: ');
accumulatore = accumulatore + inputnum;
end
media = accumulatore / n;
fprintf('La media è %.2f\n', media)
Esempio di esecuzione:
>> media_numeri
Quanti numeri vuoi inserire? 4
Inserisci un numero: 3.4
Inserisci un numero: 2.1
Inserisci un numero: 5.6
Inserisci un numero: 1.2
La media è 3.0750
Questo script calcola la media di quattro numeri inseriti dall'utente. La variabile n
è usata per determinare quante volte ripetere l'azione del loop, e la variabile accumulatore
è usata per accumulare i numeri inseriti. Alla fine, la media è calcolata come la somma di tutti i numeri divisa per il numero di numeri inseriti.
In Sintesi
In questa lezione abbiamo imparato i seguenti concetti chiave:
-
Il costrutto
for
e la variabile di iterazione:abbiamo approfondito come il ciclo
for
consenta di ripetere un blocco di istruzioni un numero definito di volte, gestendo l'iterazione tramite una variabile di loop in modo ordinato. -
Somme e prodotti progressivi:
abbiamo imparato a calcolare valori cumulativi, aggiungendo (o moltiplicando) i numeri inseriti per aggiornare in tempo reale i risultati e sfruttare operazioni più efficienti.
-
Preallocazione di vettori:
abbiamo esaminato il vantaggio di inizializzare in anticipo un vettore, evitando costosi riallocamenti di memoria e migliorando le prestazioni del codice.
Nella prossima lezione vedremo come innestare cicli for
all'interno di altri cicli, per gestire situazioni più complesse e iterazioni nidificate.