imparando matlab

Salve ragazzi… ho visto che ci sono tante discussioni su matlab ma tutte trattano di problemi complessi allora mi sono “permesso” di aprirne una per postare le richieste dei principianti

volevo sapere come funziona il comando while?
ho capito che serve per far partire un ciclo in cui io esprimo una condizione che quando è verificata il ciclo termina.

Ho trovato un esercizio che chiede quanto tempo ci vuole per fare un milione di dollari avendone 10.000 iniziali e accumulandone 10.000 ogni anno utilizzando il comando while

Allora io ho fatto una cosa del genere

k=1000000
s=10000
while (k==0)
z=(k-s)/s
end
z

facendo run mi viene però mi dice di specificare z

ma io con il comando che gli ho dato credevo di avergli detto: dammi quanto vale z quando k arriva a zero… cosa devo aggiungergli?

Manca il contatore ed è sbagliata la expression. Ossia ogni ciclo lui fa:

k è uguale a zero? NO! Allora non vede per niente il contenuto del while e poi si trova di fronte a z che non è specificata.

Io farei cosi:

tot=1000000;
s=10000;
tempo=0; %Imposti una variabile che tiene conto del tempo
while (s<tot) %finche s (che sono i soldi accumulati) sono minori di tot fai le operazioni nel while
s=s+10000; %hai detto che ogni anno guadagni 10000 giusto? quindi ad ogni iterazione aggiungi 10000
tempo=tempo+1;
end
tempo %Ti stampa il tempo in anni aggiornato dal ciclo while che ti servono per accumulare tot

grazie mille della risposta… in effetti avevo capito che nella espression gli dovevo dire quando non fare il conto e non quando farlo :face_with_head_bandage:

invece oggi facendo un altro esercizio sulle function mi serviva da creare una matrice quadrata di dimensione nxn la quale deve essere moltiplicata per un vettore.
Devo quindi calcolare il tempo di elaborazione e mettere in un vettoretutti i risultati del tempo e in un altro vettore la dimensione della matrice.
Supponendo di mettere nmax=4 io devo fare 4 operazioni diverse… nella prima moltiplico una sottomatrice 2X2 per il vettore, nella seconda operazione la sottomatrice 3X3 per il vettore e nella terza operazione la matrice 4X4 per il vettore.

Ho così creato questa istruzione
function [dim,tempi]=es2(nmin,nmax,step)
nmin=1; %imposto nmin
nmax=4; %imposto nmax
step=1; %imposto lo step
A=rand(nmax,nmax); %crea matrice con coeff casuali
v=[nmin:step:nmax]’; %crea vettore colonna
s=0;
t=0;

for i=(nmin:step:nmax)

t=tic
A(i,i)*v(i); %mi fa l’operazione con le sottomatrici e i vettori rispettivi
toc;

dim=i;
tempo=t;

end

tempo
dim

ora però come faccio a mettere i risultati di for nei due vettori colonna?
quello che mi viene sono i risultati dell’ultima operazione

Non ho ben capito il problema.

Forse perche devi fare

dim=dim+i;
tempo=tempo+t;

e li devi prima inizializzare a zero

ok ho modificato il codice come mi hai detto… a me viene tutto più o meno (difatti nel vettore tempo voglio che mi compaiano i risultati del tic toc ma su questo ci arriverò a capirlo) però cosa importante che potrebbe servirmi in futuro è che i risultati di tempo e dim devono venire separati in un vettore colonna e invece il programma me li somma.
Per farti capire se prima moltiplica la matrice 1X1 poi 2X2 poi 3X3 ecc io voglio che in dim compaia dim=[1;2;3…] e non dim=6 che è la somma dei valori.
Stessa cosa se per fare la prima operazione ci vuole 3 secondi (sparo cifre a caso) per la seconda ce ne vogliono 11 e per la terza 23 voglio che tempo diventi un vettore tempo=[3;11;23] e non tempo=37 (che è la somma dei risultati).

function [dim,tempi]=es2(nmin,nmax,step)
nmin=1; %imposto nmin
nmax=4; %imposto nmax
step=1; %imposto lo step
A=rand(nmax,nmax); %crea matrice con coeff casuali
v=[nmin:step:nmax]’; %crea vettore (??controllare??)
dim=0
tempo=0
t=0;
for i=(nmin:step:nmax)

tic
t=A(i,i)*v(i)
toc

dim=dim+i;
tempo=tempo+t;

end
tempo
dim

Se ci pensi il codice che hai scritto ad ogni iterazione del ciclo for sovrascrive le variabili dim e tempo con un nuovo valore. Devi semplicemente scrivere:

[code]k=0;
for i=(nmin:step:nmax)
k=k+1;
t=;
tic
t=A(1:i,1:i)*v(1:i)

tempo(k)=toc;
dim(k)=…;

end[/code]

Alcune cose da notare:

  • con la notazione usata assegno il tempo (con toc) come elemento k-esimo di un vettore. Stessa cosa per dim. Non posso usare i perché questo indice non parte in generale da 1 fino al valore finale con incrementi unitari. Devo perciò definire un altro indice, k, che deve essere inizializzato a 0 prima del ciclo e poi incrementato di volta in volta (io preferirei cambiare il for ma è uguale).
  • non ho ben capito cosa vorresti nel vettore dim. Le dimensioni della matrice A? Oppure del vettore t? Nel primo caso non avrebbe molto senso perché le decidi tu di volta in volta. Nel secondo caso rappresenterebbe una verifica “banale” ma didattica, perché verifichi l’output del prodotto matrice vettore. Allora in questo caso dovresti scrivere:
dim(k)=length(t);
  • il vettore t, poiché viene sovrascritto di volta in volta, conviene azzerarlo ad ogni ciclo, impostandolo come vettore nullo. In questo caso non cambierebbe nulla, ma è maggiormente corretto e didatticamente è importante.
  • per correttezza ho messo il toc subito dopo l’operazione di cui si vuole misurare il tempo. Se lo metti dopo l’assegnazione di dim, per esempio, misureresti anche quel tempo e avresti un errore.
  • Mi sembra che la definizione del vettore v sia errata. In questo modo potresti avere una dimensione diversa da quella di A. Inoltre io creerei anche il vettore v con numeri casuali:
v=rand(nmax,1);

IMPORTANTE: con questa scrittura ad ogni ciclo viene assegnato l’output di toc come elemento k-esimo del vettore tempo. Significa che al terzo ciclo tempo ha tre elementi, al quarto ne viene aggiunto uno e diventano quattro. Questo significa che ad ogni ciclo MATLAB deve incrementare l’area di memoria riservata al vettore. Questo è molto “pericoloso” perché può incrementare notevolmente il tempo necessario a matlab per fare il ciclo nel suo complesso. Con un numero esiguo di cicli la differenza è piccola, ma aumentando questa può diventare rilevante. Nel tuo caso viene inoltre reso incorretto l’output del calcolo, perché il tempo tiene conto di questa operazione fatta da MATLAB “di nascosto”. Per evitare questo problema ci sono due vie:

  1. Lasciare il problema di base ma spostare l’assegnazione del vettore dopo il toc:
appoggio=toc;
tempo(i)=appoggio;
  1. Preallocazione della variabile: in pratica tu PRIMA del ciclo for crei già una variabile di tanti 0 con le stesse dimensioni del vettore che verrà fuori dopo. In questo modo la variabile è già presente e la memoria è già allocata, quindi MATLAB deve solo sostuire allo 0 il valore giusto. Questa è la via maggiormente corretta.
tempo=zeros(length(nmin:step:nemax),1);

Me lo ricorderò sempre: in un’analisi di dati sperimentali (vettori molto grossi) sono passato da una durata di 10-15 minuti dello script a 30s-1min solo con la preallocazione… Da allora ci sto molto attento…

Noto inoltre una certa confusione nell’utilizzo della function. La function è, come dice il nome, una funzione che assegna degli output a certi input. Non ha quindi senso definire il valore degli input dentro la funzione! Se tu la richiami con valori diversi da quelli definiti:

[dim,tempo]=es2(10,30,2)

All’interno vengono sovrascritti dai tuoi e ottieni un risultato sbagliato.

Scusa per il papiro ma ho voluto spiegarti (spero) per bene tutto. Spero di non aver fatto qualche errore, che dopo ti confondo ulteriormente!

Grazie mille ARTAX… davvero gentilissimo :ok_hand:

però non mi è ancora chiaro quando mi dici

dim(k)=length(t); - il vettore t, poiché viene sovrascritto di volta in volta, conviene azzerarlo ad ogni ciclo, impostandolo come vettore nullo. In questo caso non cambierebbe nulla, ma è maggiormente corretto e didatticamente è importante.

qui vuol dire che al vettore dim sostituisco in posizione k (che quindi aumenta di uno ad ogni ciclo) lunghezza di t? :roll_eyes:

e altra cosa perchè il toc lo metti dopo tempo(k)… insomma digitare tempo(k)=toc alla fine o fare tempo(k)=tic è la stessa cosa?

:rage:

Mi spiego meglio. Innanzitutto non ho capito bene cosa vuole essere l’output dim. In particolare sono indeciso tra due possibilità:

  1. l’ordine della matrice A. In questo caso l’ordine è assegnato da te ad ogni ciclo ed è pari a i. Lo puoi assegnare con:
dim(k)=i;
  1. la lunghezza del vettore t. Allora per calcolare la lunghezza di un vettore, cioé il suo numero di elementi, si usa il comando “length”.
    Sia chiaro che il risultato numerico è lo stesso.
e altra cosa perchè il toc lo metti dopo tempo(k)... insomma digitare tempo(k)=toc alla fine o fare tempo(k)=tic è la stessa cosa? :rage:

Le due cose sono completamente diverse. Il comando toc ritorna il tempo trascorso dal precedente tic (appunto il tempo di elaborazione da trovare), mentre tic torna in output un qualche tempo assoluto di riferimento (non so di che genere). E’ come la differenza tra chiedere che ore sono (tic) e misurare un intervallo di tempo (tic + toc).

In ogni caso un consiglio importantissimo: quando hai qualche dubbio su un comando MATLAB è bene cercare informazioni nell’help, dove il comando viene trattato in modo esaustivo:

help comando

oppure

doc comando

ottimo grazie mille!

quando avrò altri dubbi saprò a chi chiedere