Come usare correttamente il ciclo while in Matlab

ScientiaPotentiaEst

Nuovo Utente
Registrato
27/3/19
Messaggi
406
Punti reazioni
117
Ciao a tutti,

è la prima volta che posto qui, quindi comincio complimentandomi con tutti i partecipanti a questa sezione perché davvero molto bravi e competenti. Vorrei approfittare della vostra competenza per chiedere lumi su un mio dubbio. Sto cercando di imparare a programmare in Matlab, vado per gradi e sto imparando i ''costrutti'' della programmazione, cioè le istruzioni condizionali (if, else if, etc.) e i cicli for e while.

Ora, da quanto ho imparato so che tutto ciò che si può ciclare in for si può ciclare in while, ma non è necessariamente vero il contrario. Per puro esercizio ho scritto un programma che attraverso il ciclo for riesca a restituirmi il valore minimo presente in una matrice e la posizione. In particolare, questo sarebbe lo script:

...

A=input('inserire matrice = ')

[n_rows, n_cols] = size(A);

minimo=A(1,1);

for i=1:n_rows;
for j=1:n_cols;
if A(i,j)<minimo;
minimo=A(i,j);
end
end
end

...

Ciò mi restituisce correttamente il minimo della matrice. Però, volendo fare la stessa cosa usando il ciclo while sbaglio qualcosa di banale, ma non riesco a capire cosa. Usando questo script:

...

minimo=A(1,1);
i=1;
j=1;

while i<=n_rows;
while j<=n_cols;
if A(i,j)<minimo;
minimo=A(i,j);
end
j=j+1;
end
i=1+i;
end

...

In questo caso lo script però mi riporta il minimo soltanto della prima riga... mentre io vorrei che mi restituisse il minimo della matrice.

Sapreste come dovrei modificare il ciclo while affinché Matlab mi restituisca il minimo della matrice?

Grazie in anticipo per l'aiuto,
Fabio
 

Paolo1956

LOREM IPSUM
Registrato
20/6/10
Messaggi
6.484
Punti reazioni
292
Scusate,

ma Matlab non ha una una funzione max/min da applicare agli array?

Perché quei cicli gridano vendetta...
 

FogOnLine

sigà sigà
Registrato
26/2/14
Messaggi
14.732
Punti reazioni
1.943
Sí, con due max() annidati (se su matrice 2D).
Il più interno restituisce il vettore che include i massimi di ciascuna colonna ed il secondo seleziona il massimo del vettore di massimi.
 

Paolo1956

LOREM IPSUM
Registrato
20/6/10
Messaggi
6.484
Punti reazioni
292
Comunque, per chiarire le idee al nostro amico:

- quando sappiamo esattamente quanti passi occorrono è più corretto un ciclo for, se non altro è più chiaro e intellegibile
- quando non lo sappiamo, perché deriva da una condizione da testare ad ogni ciclo si usa while.

Esempino da squola:

Codice:
MaxCommonDiv [x,y]
while(y>0)
[x,y] = [y, x mod y];

return x

perché non hai idea di quanti passi occorrano
 

ScientiaPotentiaEst

Nuovo Utente
Registrato
27/3/19
Messaggi
406
Punti reazioni
117
Sì Paolo, ci sono le funzioni max e min ma il mio obiettivo è quello di imparare ad usare il ciclo while. So che risparmierei molti passaggi e so anche che in questo caso - conoscendo il numero di iterazioni da fare avendo sia il numero di righe che di colonne - il ciclo for sia più efficiente del while, infatti l'ho usato. Però, siccome so che qualsiasi cosa che si può ciclare in for si può ciclare anche in while, vorrei riuscire a trovare il minimo della matrice anche con il ciclo while. Ti ringrazio per l'intervento.

Grazie Cren, sono riuscito a risolvere con il tuo suggerimento. In effetti era una banalità...
 

FogOnLine

sigà sigà
Registrato
26/2/14
Messaggi
14.732
Punti reazioni
1.943
Se si legge un articolo di giornale che abbia lettere mancanti o parole mal scritte il nostro cervello "corregge" automaticamente gli errori e restituisce il senso corretto delle frasi. Con meccanismo analogo, quanto son più banali gli errori tanto più son difficili da scovare da chi ha scritto il codice. :)

Mi permetto un suggerimento su Matlab. Capisco la volontà di sperimentare le singole istruzioni, ma la sua caratteristica principale è poter essere utilizzato in forma compatta per trattare matrici e porzioni delle stesse, evitando peraltro di usare come indici i e j che in Matlab sono utilizzati per I numeri immaginari (meglio abituarsi da subito a indici ii e jj).

Un esempio, essendo A una matrice 2d di cui si voglia trovare il max e la sua posizione nella matrice.

[max_val,pos_idx]=max(A(: )
[row_idx,col_idx]=ind2sub(size(A),pos_idx)

La notazione A(: )fa interpretare la matrice 2d come un vettore colonna, per questo la posizione del massimo all'interno della matrice va poi ricavata opportunamente.
 

Cren

Nuovo Utente
Registrato
6/10/09
Messaggi
10.600
Punti reazioni
615
Scusate,

ma Matlab non ha una una funzione max/min da applicare agli array?

Perché quei cicli gridano vendetta...
Fate i puristi della vettorizzazione solo perché è il linguaggio sbagliato, se li avesse scritti in C++ con due iteratori const di std::vector< double > nessuno gli avrebbe detto niente :p
 

Paolo1956

LOREM IPSUM
Registrato
20/6/10
Messaggi
6.484
Punti reazioni
292
Fate i puristi della vettorizzazione solo perché è il linguaggio sbagliato, se li avesse scritti in C++ con due iteratori const di std::vector< double > nessuno gli avrebbe detto niente :p

Sì, però tieni conto che i tempi cambiano e queste features sono oggi disponibili in una vasta gamma di linguaggi :)
 

tesiag

Nuovo Utente
Registrato
20/8/10
Messaggi
1.742
Punti reazioni
37
programmazione funzionale? (mathematica)
 

amartya78

Nuovo Utente
Registrato
15/9/08
Messaggi
9.637
Punti reazioni
644
Ciao a tutti,



Ora, da quanto ho imparato so che tutto ciò che si può ciclare in for si può ciclare in while, ma non è necessariamente vero il contrario.

Non entro nel merito del motivo per cui il risultato non ti viene in while (tra l'altro credo che altri ti hanno già risposto) ma voglio sottolineare l'effetto pratico che si ha usando while al posto di for quando è possibile utilizzare for.

L'effetto pratico è che il processo computazionale ha un costo enorme ed inutile.

Nell'ipotesi comune che tu sai già la dimensione dell'array (lo sai o fai in modo di saperlo) succede che sapendolo tu puoi pre-allocare la memoria mediante per esempio in Matlab la funzione zeros con tipo M = zeros(n,m) prima di iniziare il ciclo for. Il che significa che stai inizializzando la matrice cioè vai a puntare le celle di memoria della RAM dandone l'indirizzo al ciclo for che altrimenti dovrà cercalo di volta in volta con un enorme costo computazionale. (Considera che Matlab deriva da C++ e quindi la tecnica del C++, il puntatore, viene ereditata da Matlab). Ora se userai Matlab, lo farai solo se dovrai fare calcoli matriciali, veloci e complessi altrimenti c'è Python o altri free.
Tra l'altro il ciclo for, sempre ai fini della velocità, può essere utilizzato per il calcolo parallelo tramite la funzione parfor. E questo lo puoi fare tramite solo il ciclo for in quanto per utilizzare il calcolo parallelo non devi avere una broadcast variable. Significa che per ogni valore che assume l'indice nel ciclo l'informazione tra un array e l'altro non deve dipendere dal valore assunto dall'array nell'indice precedente, in altri termini l'informazione trasmessa deve essere definita ab origine senza più la necessita di acquisirne altra. Questa cosa ovviamente non è possibile per il ciclo while che serve proprio a trovare un valore che dipende dagli indici precedenti.

Quindi se alla fine dell'apprendimento di Matlab non vuoi trovarti a manovrare un calesse quando potevi manovrare la Enterprise e la velocità a curvatura ti conviene non sottovalutare la potenza del ciclo for, anzi, poichè immagino le possibili applicazioni future ti consiglio caldamente ad apprenderlo portandolo alle estreme conseguenze.