Che materia stai cercando?

Anteprima

ESTRATTO DOCUMENTO

20

h=0;

j=ones(1,150);

for i=1:150

vtot=0;

while j(i)<=5 & vtot<100

v=rand()*20+10;

vtot=vtot+v;

j(i)=j(i)+1;

end

if vtot>=100

h=h+1;

end

end

disp(‘Il limite di tonnellate è stato raggiunto (giorni):’);

disp(h);

6) Possiamo quindi ora plottare il grafico del numero di ingressi in cava al giorno con il

semplice comando plot(j-1):

clear Nota importante:

h=0; Uno dei problemi più comuni con il ciclo while

j=ones(1,150); capita quando dopo il ciclo stesso andiamo a

for i=1:150 “lavorare” con la variabile che funge da suo

vtot=0; indice, ovvero quella che nell’esempio qui a

while j(i)<=5 & vtot<100 sinistra è la variabile j(i) (in realtà j in questo

v=rand()*20+10; programma è un vettore, ma stiamo

vtot=vtot+v;

j(i)=j(i)+1; considerando ogni sua casella j(i) come se fosse

end la variabile indice riferita al giorno i). Se

if vtot>=100 proviamo ad eseguire il programma usando

h=h+1; plot(j) al posto di plot(j-1) noteremo

end zoommando nel grafico che i numeri di ingressi

end in cava giornalieri sono quasi sempre 6 e

disp(‘Il limite di tonnellate è stato raggiunto raramente 5, quando in realtà dovrebbero

(giorni):’);

disp(h); essere quasi sempre 5 e raramente 4. Questo

plot(j-1); accade perché se per esempio ipotizziamo di

essere arrivati al 5° camion (quindi j(i)=5) e che

vtot sia ancora minore di 100, il programma

eseguirà tutte le righe all’interno del while fino

ad arrivare a j(i)=j(i)+1, incrementandola a 6.

Poi ritornerà al while e verificherà che j(i)<=5

non è più 21

soddisfatta e di conseguenza uscirà da questo ciclo. Nonostante siano stati mandati 5 camion,

la nostra variabile j(i) (che usavamo per tenerne il conto) ci dice che sono 6. Questo

problema non ci tocca in tutti i programmi, ma in questo si: noi infatti dobbiamo plottare

questo dato che però risulta falsificato. Siccome tutti i valori del vettore j sono sfalsati di un

+1, il modo più veloce per risolvere questo problema è usare plot(j-1), dove j-1 è il vettore j

a cui in ogni casella è stato sottratto un 1.

In questo caso siamo stati fortunati, a volte è più complicato risolvere questo problema.

Ricordatevi di porre una particolare attenzione quando si richiamano gli indice del ciclo while

dopo il corrispondente end.

7) Ci rimane solo da plottare il grafico del numero delle tonnellate giornaliere e da aggiungere

la legenda.

clear Analogamente a quanto fatto prima dobbiamo

h=0; cercare la variabile che si occupa delle

j=ones(1,150); tonnellate giornaliere e farla diventare un

vtot=zeros(1,150); vettore. La variabile in questione è vtot. Agiamo

for i=1:150 come con j con l’unica differenza che dobbiamo

while j(i)<=5 & vtot(i)<100 usare il comando zeros per definire il vettore

v=rand()*20+10; vtot poiché il valore iniziale di ogni giorno deve

vtot(i)=vtot(i)+v; essere 0 e non 1.

j(i)=j(i)+1;

end Aggiungiamo quindi anche il secondo plot, sotto

if vtot(i)>=100 un adeguato hold on (senza Matlab

h=h+1; mostrerebbe solo uno dei due grafici) e una

end legenda con il comando legend.

end

disp(‘Il limite di tonnellate è stato raggiunto In questo caso dobbiamo stampare il vettore

(giorni):’); vtot che non è influenzato da j, quindi non

disp(h); dobbiamo aggiungere o modificare niente,

plot(j-1); funziona già perfettamente.

hold on;

plot(vtot);

legend(‘Numero ingressi in cava giornalieri’ , ’Numero di tonnellate conferite

quotidianamente’);

Il problema poteva essere risolto in moltissimi altri modi: questo è uno fra i più compatti e

senza strani giri complessi ma l’importante è che alla fine svolga il suo compito

correttamente.

Compito 15/09/2017:

Un azienda che si occupa di movimento terra conferisce una quantità modellabile di detriti v,

modellabile come una variabile casuale intera compresa fra 0 e 40 tonnellate. L’azienda può

mandare 10 camion a giorno; tuttavia deve interrompere il conferimento se la terra conferita

totale raggiunge o supera la quota limite di 4*10^7 Kg. (Per comodità il controllo del limite

delle tonnellate va effettuato alla fine del giorno).

Si scriva un programma che:

- Simuli il conferimento in cava per 200 giorni;

- Riporti a schermo se è stato raggiunto il limite dei giorni oppure no;

- Riporti su un grafico l’andamento giornaliero delle tonnellate di terra totali estratte (ovvero

ad ogni giorno X deve corrispondere le tonnellate di terra estratte fino a quel giorno) con una

curva di colore rosso e con scala logaritmica lungo l’asse delle ordinate.

Questo compito tratta dello stesso tema di quello visto precedentemente però, sebbene sia

uguale, in realtà chiede cose diverse.

1) Possiamo fare gli stessi ragionamenti visti fino al punto 3 del problema precedente ma con

alcune differenze:

- Questa volta il ciclo interno dovrà essere un ciclo for poiché non c’è nessuna condizione di 22

uscita nel giorno mentre il ciclo esterno dovrà essere un while, poiché questa volta la

condizione di uscita riguardante il limite di tonnellate non è giornaliero ma di quelle totali

conferite durante il contratto.

- Sempre per il motivo citato prima, vtot dovrà essere azzerato prima di entrambi i cicli visto

che deve tenere conto adesso delle tonnellate totali e non più di quelle giornaliere.

Possiamo quindi scrivere l’inizio del nostro programma e risolvere anche il primo punto del

problema:

clear

vtot=0;

i=1;

while i<=200 & vtot<40000 %Attenzione: il testo ci dà il limite in Kg e non in tonnellate!!!

for j=1:10

v=fix(rand()*41); %Questa volta serve il fix e il 40+1 visto che il testo ci richiede dei

numeri casuali interi

vtot=vtot+v;

end

i=i+1;

end

2) Per il secondo punto basta inserire un if dopo i cicli e chiedersi se i<=200:

- Nel caso in cui questa condizione risulti vera, vorrà dire che non è stato raggiunto il limite

dei giorni poiché è stato superato il limite delle tonnellate totali.

- Nel caso in cui questa condizione risulti falsa, vorrà dire che è stato raggiunto il limite.

Possiamo quindi stampare a schermo queste frasi tramite due disp:

clear

vtot=0;

i=1;

while i<=200 & vtot<40000

for j=1:10

v=fix(rand()*41);

vtot=vtot+v;

end

i=i+1;

end

if i<=200 Nota: in realtà il limite dei giorni viene raggiunto

disp(‘Non è stato raggiunto il limite di se i<200. Noi però scriveremo i<=200 solo per il

giorni’); solito problema causato dal while. Infatti noi in

else teoria raggiungeremo il limite dei giorni nel

disp(‘è stato raggiunto il limite di giorno 200, ma siccome la i alla fine di quel

giorni’); giorno viene incrementata, il suo valore

end corrispondente al 200esimo giorno è i=201 e

non i=200.

3) Per l’ultimo punto, come nel problema precedente, siamo costretti a modificare qualcosa:

dobbiamo trasformare di nuovo vtot in un vettore per poterlo plottare. Questa volta però sarà

più complicato poiché se noi usassimo come prima il comando zeros per definire il vettore

vtot questo avrà lunghezza 200. Il che potrebbe non sembrare un problema però mettiamo

che il 130esimo giorno venga raggiunto il limite di tonnellate e che quindi l’azienda smetta di

conferire terra: la casella vtot(130) conterrà un numero maggiore a 40000 mentre quelle

successive varranno 0. Questo si traduce che nel grafico la curva fino al giorno 130 sarà

crescente, per poi calare a picco fino all’asse delle ascisse e continuare su di essa fino al 23

giorno 200. Per risolvere questo problema (che non varrebbe quasi nulla come errore nel

compito) mi vengono in mente due modi:

- Il primo consiste nell’ingegnarsi e nascondere il problema, ovvero useremo il comando zeros

per definire vtot ma nasconderemo quella parte di grafico che non ci interessa. Come? Con il

comando xlim([0 i]). Metteremo i come estremo superiore poiché se dovessimo raggiungere

il limite di tonnellate prima che i raggiunga 200, questa si fermerà nel giorno in cui tale limite

è stato raggiunto.

- Il secondo metodo è più complicato ma risolve correttamente il problema. Sfrutta un altro

modo per generare vettori offerto da Matlab che non ho citato mai. In pratica possiamo

considerare definire vtot(1)=0, generando un vettore di lunghezza 1, come se fosse una

variabile. Successivamente, quando verranno svolte le operazioni vtot(i)=vtot(i)+v questo

andrà ad incrementare la sua lunghezza del valore di i. In altre parole aggiungerà una nuova

casella ad ogni giro e di conseguenza, se il ciclo dovesse stopparsi prima di i=200 il vettore

vtot sarà lungo precisamente quanto il giorno in cui il ciclo si è fermato. Facendo così non c’è

bisogno di usare xlim e il problema sarà risolto, non nascosto.

Una volta scelto quale metodo usare bisogna stare attenti ad non utilizzare il comando plot

questa volta ma il comando semilogy() poiché ci viene chiesto di usare una scala logaritmica

nelle ordinate e di aggiungere dentro l’argomento ‘r’ per creare una curva rossa.

Attenzione: da qui in poi andiamo alla ricerca del programma “perfetto” quindi non

preoccupatevi se alcune operazioni sembrano difficili o non le capite, alla fine ho messo

anche una versione accettabilissima del programma che ignora questi problemi da

perfezionisti che cercheremo di risolvere qui sotto.

Problema risolto con il primo metodo:

clear

vtot=zeros(1,200);

i=1;

while i<=200 & vtot(i)<40000

for j=1:10

v=fix(rand()*41);

vtot(i)=vtot(i)+v;

end

i=i+1;

end

if i<=200

disp(‘Non è stato raggiunto il limite di giorni’);

else

disp(‘è stato raggiunto il limite di giorni’);

end

semilogy(vtot, ‘r’);

xlim([0 i]);

Problema risolto con il secondo metodo:

clear

i=1;

while i<=200 & vtot(i)<40000

vtot(i)=0;

for j=1:10

v=fix(rand()*41);

vtot(i)=vtot(i)+v;

end

i=i+1;

end

if i<=200 24

disp(‘Non è stato raggiunto il limite di giorni’);

else

disp(‘è stato raggiunto il limite di giorni’);

end

semilogy(vtot, ‘r’);

4) C’è una brutta notizia però: entrambi i programmi ora come ora, non funzionano come

dovrebbero. Infatti la condizione di uscita del while vtot(i)<40000 non verrà mai soddisfatta

poiché la casella vtot(i) all’inizio del ciclo varrà sempre 0. Ci siamo infatti scordati di dire alla

fine del ciclo, dopo i=i+1 che vtot(i)=vtot(i-1), ovvero che ogni giorno la casella di vtot

corrispondente dovrà iniziare con il valore raggiunto la sera del giorno prima, ovvero quello

della casella prima. Ma nemmeno così va bene al 100% poiché ogni volta che il limite delle

tonnellate verrà raggiunto la casella vtot(i) e la casella vtot(i-1) avranno lo stesso valore e il

giorno in cui è stato superato il limite sarebbe i-1.

Primo metodo corretto:

In questo caso il problema risulta marginale, dobbiamo semplicemente aggiungere come

abbiamo detto prima il vtot(i)=vtot(i-1) e utilizzare lo stesso trucchetto di prima per

“mascherare” il problema, però questa volta dovrà essere xlim([0 i-1]) :

clear

vtot=zeros(1,200);

i=1;

while i<=200 & vtot(i)<40000

for j=1:10

v=fix(rand()*41);

vtot(i)=vtot(i)+v;

end

i=i+1;

vtot(i)=vtot(i-1);

end

if i<=200

disp(‘Non è stato raggiunto il limite di giorni’);

else

disp(‘è stato raggiunto il limite di giorni’);

end

semilogy(vtot, ‘r’);

xlim([0 i-1]);

Secondo metodo corretto:

In questo caso la faccenda è più tosta poiché il nostro vettore vtot avrà una casella in più.

L’unico modo di evitare questo problema è posizionare il comando vtot(i)=vtot(i-1) dentro

un if che lo esegua solo se vtot(i-1)<40000 e che esca dal ciclo con un break nel caso

contrario. Di conseguenza possiamo pure togliere la condizione vtot(i)<40000 dal ciclo

while poiché inutile (anche il ciclo while potrebbe essere sostituito ora con un for visto che

non c’è più la necessità di una seconda condizione di uscita, ma attenzione alcuni indici vanno

modificati quindi meglio lasciare il while).

clear

i=1;

vtot(1)=0; %bisogna eliminare il vtot(i)=0 di prima e metterci questo in questa posizione

while i<=200 25

for j=1:10

v=fix(rand()*41);

vtot(i)=vtot(i)+v;

end

i=i+1;

if vtot(i-1)<40000 & i<=200 %perchè se V(200) non dovesse superare il limite di

tonnellate, creerebbe lo stesso

vtot(i)=vtot(i-1); %V(201)

else

break;

end

end

if i<=200

disp(‘Non è stato raggiunto il limite di giorni’);

else

disp(‘è stato raggiunto il limite di giorni’);

end

semilogy(vtot, ‘r’);

Problema risolto in maniera accettabile:

clear

vtot=zeros(1,200);

i=1;

while i<=200 & vtot(i)<40000

for j=1:10

v=fix(rand()*41);

vtot(i)=vtot(i)+v;

end

i=i+1;

vtot(i)=vtot(i-1);

end

if i<=200

disp(‘Non è stato raggiunto il limite di giorni’);

else

disp(‘è stato raggiunto il limite di giorni’);

end

semilogy(vtot, ‘r’);

Il problema risolto in questa maniera ignora il fatto che nel grafico compaiano anche le caselle

comprese fra il giorno in cui si è fermato il ciclo e il 200esimo giorno. Non è nemmeno un

errore molto grave in questo caso poiché stiamo usando il comando semilogy e non il plot:

infatti se nel plot questo fatto produrrebbe un crollo nel grafico dal valore massimo di vtot

allo 0, con la scala logaritmica questo non accade.

Grafico di semilogy(vtot) Grafico di plot(vtot) 26

Compito 23/01/2018:

La società StradePiù vi ha commissionato uno studio comparativo sullo sgretolamento di 6 tipi

di asfalto da utilizzare per il rifacimento del manto stradale.

1) Si simuli per ciascun tipo di asfalto l’erosione e (in centimetri) all’aumentare dei giorni

n

n. Il modello matematico di simulazione dell’erosione è:

{ c

(s∗w ) se n=1

=

e n

n c

( )

+[ +e ]

e s w se n>1

n−1 n−1 n

Dove s=0.012cm, w è una variabile casuale intera uniformemente distribuita con valori

n

fra 0 e 1 (adimensionale) e c è una costante adimensionale che varia per ogni asfalto

come riportato in Tabella 1. Per ogni asfalto la simulazione deve interrompersi al giorno

365 (compreso) o se l’erosione supera 1 cm.

2) Dopo la simulazione, si riportino a schermo gli indici degli asfalti validi, cioè quelli che

hanno raggiunto o superato i 250 giorni di simulazione.

3) Si riportino su uno stesso grafico le curve e relative agli asfalti 1 e 3 in funzione dei

n

giorni n; ciascuna curva deve terminare in corrispondenza del proprio massimo valore

di simulazione. Si inserisca un opportuna legenda.

Tabella 1

Asfalto 1 2 3 4 5 6

c 2 2.05 2.1 2.15 2.2 2.25

Svolgimento:

Questo problema a primo impatto sembra completamente diverso: in effetti lo è, però sfrutta

dei concetti che abbiamo visto anche negli altri programmi.

1) Innanzitutto dobbiamo scrivere le variabili e le costanti che ci da come dati il testo. s sarà

semplicemente una variabile, w deve essere un numero casuale intero compreso fra 0 e 1

(quindi può essere solo 0 o 1) e deve cambiare ogni giorno della simulazione; infine c deve 27

assumere un valore diverso per ogni tipo di asfalto, quindi basterà scriverlo sotto forma di

vettore di 6 caselle, nella quale ognuna rappresenta una delle 6 tipologie di asfalto.

clear

s=0.012; %l’unità di misura non interessa a Matlab

w=fix(rand()*2);

c=[ 2 , 2.05 , 2.1 , 2.15 , 2.2 , 2.25 ];

2) Dopo aver risolto i compiti precedenti, dovrebbe sembrarci facile capire che per compiere

questa simulazione dovremmo usare dei cicli: in particolare ci accorgiamo che ogni singolo

asfalto deve essere testato per 365 giorni o finchè la sua erosione non superi 1 cm. Di

conseguenza possiamo notare che siccome ogni asfalto viene testato con la stessa

metodologia, possiamo usare un ciclo for con indice i che vada da 1 a 6, che mi indica quale

dei 6 asfalti sto testando; poi all’interno di questo ciclo useremo un ciclo while con indice n

che servirà a simulare ogni giorno. Le sue condizioni di uscita le aggiungeremo dopo:

clear

s=0.012;

c=[ 2 , 2.05 , 2.1 , 2.15 , 2.2 , 2.25 ];

for i=1:6

n=1;

while

w=fix(rand()*2); % Ho spostato qui w perché voglio che cambi ogni giorno.

n=n+1;

end

end

3) Dobbiamo pensare adesso come tradurre e del testo, ovvero l’erosione. Questa grandezza

n

non potrà essere una variabile, poiché dando uno sguardo al suo modello matematico

e

notiamo che dovremo lavorare anche con il valore assunto il giorno precedente ( ):

n−1

deve essere quindi un vettore, che chiameremo e, che indicherà in ogni sua casella lo

sgretolamento che l’i-esimo asfalto esaminato ha subito fino a quel giorno n.

Siccome sappiamo che la simulazione potrebbe interrompersi prima del giorno 365 e che

leggendo la domanda nel punto 3, dovremmo poi fare il grafico di questo vettore per gli asfalti

1 e 3, ci conviene strutturare questo vettore come abbiamo fatto nel secondo metodo del

compito scorso, ovvero dichiarando solo la prima casella e aggiungendo le caselle successive

ogni giorno.

In particolare notiamo che questo sistema può tornarci utile perché possiamo dichiarare la

prima casella di e usando la formula del modello matematico nel caso n=1, mettere

l’incremento della n subito sotto al while (così facendo è come se il ciclo partisse da n=2 e

oltretutto così risolviamo anche il fastidioso problema del ciclo while) e mettere la formula di

e per il caso n>1 dentro il ciclo while:

clear

s=0.012;

c=[2,2.05,2.1,2.15,2.2,2.25];

for i=1:6

w=fix(rand()*2); %Devo mettere la w anche qua perchè mi serve per il valore della casella

e(1)

e(1)=(s*w).^c(i);

n=1;

while n<365 && e(n)<=1 % n < 365 perchè subito dopo c’è n=n+1; quindi se n fosse

365, tutte le operazioni che

n=n+1; % faremo con lei saranno riferite a 366, per esempio verrà

generata la casella e(366). 28

w=fix(rand()*2); % Ho aggiunto anche e(n)<=1 come condizione di uscita

quando l’erosione arriva a 1cm.

e(n)=e(n-1)+((s+e(n-1))*w).^c(i);

end

end

4) Il primo punto è stato completato. Per risolvere la seconda domanda ci conviene generare

un nuovo vettore di lunghezza 6 che chiameremo asfalti_validi tramite il comando zeros.

Ogni casella corrisponde ad un tipo d’asfalto; quando il valore al suo interno è 0, l’asfalto non

avrà superato il 250-esimo giorno, altrimenti il suo valore sarà 1.

Dobbiamo quindi inserire un if dentro il ciclo while che cambierà il valore di asfalti_validi(i)

in 1 quando n raggiunge il valore 250.

Infine per stampare a schermo gli indici degli asfalti risultati validi ci basterà sfruttare un for

con dentro un if che mostrerà a schermo l’indice solo se nella corrispondente casella dentro

asfalti_validi è presente un 1:

clear

s=0.012;

c=[2,2.05,2.1,2.15,2.2,2.25];

for i=1:6

w=fix(rand()*2);

e(1)=(s*w).^c(i);

n=1;

while n<365 && e(n)<=1

n=n+1;

w=fix(rand()*2);

e(n)=e(n-1)+((s+e(n-1))*w).^c(i);

if n==250

asfalti_validi(i)=1;

end

end

end

disp(‘Gli asfalti validi sono i numeri: ’);

for i=1:6

if asfalti_validi(i) == 1

disp(i);

end

end

5) Per rispondere alla domanda 3 basterà aggiungere un if sotto al while ma dentro al for

che plotti e se i è 1 o 3:

clear

s=0.012;

c=[2,2.05,2.1,2.15,2.2,2.25];

for i=1:6

w=fix(rand()*2);

e(1)=(s*w).^c(i);

n=1;

while n<365 && e(n)<=1

n=n+1;

w=fix(rand()*2);

e(n)=e(n-1)+((s+e(n-1))*w).^c(i);

if n==250

asfalti_validi(i)=1;

end

end

if i==1 || i==3

plot(e); 29

hold on; % Perché voglio che entrambi i grafici siano nella solita finestra

end

end

disp(‘Gli asfalti validi sono i numeri: ’);

for i=1:6

if asfalti_validi(i) == 1

disp(i);

end

end

legend(‘Asfalto 1’,’Asfalto 3’); % Aggiungo anche l’opportuna legenda

Il programma sarebbe finito, infatti se lo proviamo ad eseguire una decina di volte non sembra

esserci nessun grave problema.

Però uno deve sempre riflettere su cosa gli potrebbe essere sfuggito e in qualche errore che

può presentarsi raramente. Possiamo per esempio notare che gli ultimi asfalti sono sempre

validi mentre i primi no. Questo non è un errore, deriva dalla formula: infatti gli ultimi asfalti

hanno un c più grande, ed essendo c all’esponente di un numero che per la maggior parte dei

giorni è minore di 1, provoca che gli asfalti con c maggiore resistono più a lungo. Se fosse

sempre così (sperimentalmente accade sempre) non ci sarebbero problemi; ciò non toglie che

nella formula compare anche w che quando assume il valore 0, congela l’erosione (cioè

l’erosione dell’asfalto di quel giorno è pari a 0). Potrebbe quindi capitare che durante il test

del primo asfalto, w assuma moltissime volte il valore 0 e che quindi il primo asfalto resisti più

a lungo del secondo. Questo però non deve succedere nel nostro programma perché se

ipotizziamo che il primo asfalto resista 100 giorni e il secondo 70, il vettore e del primo asfalto

ha 100 caselle come è giusto che sia; il secondo però ne ha sempre 100 dove le prime 70

hanno i giusti valori dell’erosione del secondo asfalto, mentre le ultime 30 contengono gli

stessi valori delle ultime 30 del primo asfalto. Questo accade perché noi abbiamo scritto un

programma che aggiunga delle caselle al vettore e quando servono, ma una volta aggiunte

questo nei cicli successivi manterrà la lunghezza massima raggiunta fino a quel momento. Per

risolvere questo problema nel modo più svelto possibile possiamo notare che se w fosse

uguale per ogni asfalto ma che cambi di giorno in giorno (ovvero che nel primo giorno vale 0

per tutti e 6 gli asfalti, nel secondo 1, ecc..) come se w dipendesse dalle precipitazioni e la

simulazione si svolgesse all’aperto con tutti e 6 gli asfalti che subiscono la stessa pioggia,

matematicamente ogni asfalto non può durare più a lungo di uno con indice maggiore. Per

fare ciò quindi basta togliere tutti i w=fix(rand()*2); che abbiamo nel programma,

dichiararlo sotto forma di vettore di lunghezza 365 prima del for e ricordarci di sostituire w

con w(n) nella formula dell’erosione dentro il ciclo while e con w(1) invece in quella del

primo giorno:

clear

s=0.012;

c=[2,2.05,2.1,2.15,2.2,2.25];

w=fix(rand(1,365)*2);

for i=1:6

e(1)=(s*w(1)).^c(i); %sostituisco w con w(1)

n=1;

while n<365 && e(n)<=1

n=n+1;

e(n)=e(n-1)+((s+e(n-1))*w(n)).^c(i); %sostituisco w con w(n)

if n==250

asfalti_validi(i)=1;

end

end

if i==1 || i==3

plot(e);

hold on;

end

end

disp(‘Gli asfalti validi sono i numeri: ’);

for i=1:6 30

if asfalti_validi(i) == 1

disp(i);

end

end

legend(‘Asfalto 1’,’Asfalto 3’);

L’ipotesi che abbiamo fatto è realistica ed era il modo più veloce per evitare il problema. Se

però il testo fosse stato diverso e ci avesse vietato di fare questo ragionamento, avremmo

potuto risolvere questo problema usando un trucchetto forse più semplice, che è spiegato

nella pagina 8 del capitolo B05 delle slide dei professori di cui non vi ho mai parlato: possiamo

infatti richiamare solo alcune caselle dei vettori e delle matrici utilizzando questa notazione:

nome_matrice(riga_iniziale : riga_finale, colonna iniziale : colonna_finale)

( ) ( )

1 2 3 2 3

(1

A= A : 3,2:3)= (1,1

A :3)=(1 2 3)

Es: se ----> oppure

4 5 6 5 6

7 8 9 8 9

Di conseguenza basterà agire sul plot e stampare solo i valori di e compresi fra 1 e n:

clear

s=0.012;

c=[2,2.05,2.1,2.15,2.2,2.25];

for i=1:6

w=fix(rand()*2);

e(1)=(s*w).^c(i);

n=1;

while n<365 && e(n)<=1

n=n+1;

w=fix(rand()*2);

e(n)=e(n-1)+((s+e(n-1))*w).^c(i);

if n==250

asfalti_validi(i)=1;

end

end

if i==1 || i==3

plot(e(1:n));

hold on;

end

end

disp(‘Gli asfalti validi sono i numeri: ’);

for i=1:6

if asfalti_validi(i) == 1

disp(i);

end

end

legend(‘Asfalto 1’,’Asfalto 3’); 31

Consigli:

- Chiudere subito gli end appena si apre un ciclo o un if: At

A volte ci si può dimenticare di qualche end e nella command window ci apparirà l’errore “

least one END is missing…”: se dovesse comparire questo errore vuol dire che sono stati

aperti dei cicli e degli if ma che non sono stati chiusi tutti con i rispettivi end.

Es:

for i=1:n

somma=somma+i;

if somma>10

break;

end

%manca l’end del for!

Per evitare di incorrere in questo errore secondo me il metodo migliore consiste nel lasciare

una riga vuota ogni volta che usiamo un for, while o if e scrivere subito l’end nella riga

sotto; prendendo questa abitudine non ci si scorderà mai degli end.

Es: 2) 3)

1) for i=1:n for i=1:n

for i=1:n somma=somma+i; somma=somma+i;

if if somma>10

end break;

end end

end end

- Leggere gli errori di Matlab:

Esistono due tipi di errori nella programmazione: di sintassi o logici. Nella prima categoria

rientrano gli errori come un comando scritto male o incompleto, quindi quegli errori stupidi

che non fanno nemmeno partire il programma.

Se sono presenti invece errori logici il programma potrebbe pure partire, ma non fa quello che

ci aspettavamo. Matlab non è in grado di percepire gli errori logici perché non sa quale deve

essere lo scopo del programma; riesce però a trovare e segnalarci gli errori di sintassi. Infatti

basta leggere la command window, i messaggi scritti di rosso ci spiegano in inglese l’errore e

in che linea si trova. Imparare a comprendere i messaggi degli errori può rendere istantanea

la ricerca dell’errore.

Un breve elenco degli errori segnalati da matlab:

Testo dell’errore Spiegazione

Subscript indices must either be real Se appare questo errore vuol dire che il

positive integers or logicals vostro programma sta cercando di trovare

una casella di un vettore o di una matrice ma

l’indice usato non è un numero intero positivo

(anche lo 0 non va bene quindi).

Es: V(i)=2 ma i vale 0, 0.1 o -1 e quindi non

può richiamare una casella del vettore che

non esiste (non esiste la casella -1).

Probabilmente avete stabilito male il range

dell’indice. Di solito capita quando avete un

vettore V di lunghezza n e lo scorrete con un

ciclo for con i=1:n. Poi in una parte del

programma interagite con la casella V(i-1): è

ovvio che nel primo giro del ciclo questa

casella non verrà trovata poiché V(0) non

esiste. Per risolvere il problema 32

probabilmente dovrete modificare il valore di

i da 2:n, ma esaminate bene il caso, forse

non è l’unica modifica che dovete apportare.

Index exceeds matrix dimensions Errore simile a quello di prima ma più

comune: matlab vi sta segnalando che state

cercando una casella di un vettore o di una

matrice in una posizione più grande delle

dimensioni del vettore/matrice stessa.

Es: data la matrice M di dimensioni 3 5, in un

x

punto del programma state cercando la

casella M(10,15), che non esiste.

Probabilmente anche in questo caso avete

stabilito male il range dell’indice; di solito

capita quando avete un vettore V di

lunghezza n e lo scorrete con un ciclo for con

i=1:n. Poi in una parte del programma

interagite con la casella V(i+1): è ovvio che

nell’ultimo giro del ciclo questa casella non

verrà trovata poiché V(11) non esiste. Per

risolvere il problema probabilmente dovrete

modificare il valore di i da 1:n-1, ma

esaminate bene il caso, forse non è l’unica

modifica che dovete apportare.

‘nome’

Undefined fuction or variable Questo messaggio comparirà quando fate un

errore di battitura e che quindi scrivete male

il nome di una variabile o di un comando. Un

altro motivo potrebbe essere che non siete

stati attenti al maiuscolo: magari state

chiamando una variabile ‘A’ ma prima l’avete

definita come ‘a’.

Unbalanced or unexpected parenthesis Molto simile all’errore di prima solo che

or bracket questa volta avete messo le parentesi o altri

simboli come gli apostrofi usati per scrivere

del testo nei comandi come il disp in un

numero dispari, ovvero non avete chiuso

tutte le coppie di questi simboli.

Es: fix(rand() manca una parentesi da

chiudere.

At least one END is missing: the Errore simile ai due precedenti: non sono

statement may begin here stati messi tutti gli end per ogni for, while e if

usati.

Operands to the || and && operators È forse l’errore più difficile da comprendere.

must be convertible to logical scalar Infatti nonostante dal testo dell’errore sembri

values. che il problema abbia a che fare con gli

operatori logici && e ||, in realtà la parte che

ci deve interessare è l’intera riga dove questi

compaiono e che ci segna come errore.

Per risolvere questo problema dovete

rileggere dettagliatamente quello che avete

scritto in quella riga, che probabilmente

conterrà una condizione di un while o di un

if. Nella maggior parte dei casi l’errore

consiste nell’aver richiamato una variabile

che in realtà è un vettore o una matrice.

Es:

i=0;

v=zeros(1,10);

if v==2 && i<10

v=3; 33

end

Nell’esempio qui sopra sto richiamando nella

condizione dell’if la variabile v: il programma

mi segnalerà questo errore perché sopra ho

definito v come vettore e non come

variabile, di conseguenza v==2 non

significa niente, molto probabilmente mi

interessa invece verificare v(i)==2, ovvero

la casella in posizione i di v.

- Usare l’autocorrezione di Matlab per inserire i ‘ ; ’ alla fine delle righe che lo

richiedono:

Matlab ci mette a disposizione un

comodo strumento di

“autocorrezione”; non illudetevi

perchè non risolve nessun problema

grave, però può essere utile

soprattutto per capire alla fine di quali

righe bisogna inserire il “;”.

Infatti a destra di ogni riga in cui non

avete inserito il “;” , se invece era

richiesto, apparirà un trattino

arancione che ve lo ricorderà.

In realtà questo trattino non appare

solo in questo caso: un altro caso

frequente è quando usate gli

operatori logici & e | e quasi sempre

Matlab vi dirà che è meglio usare &&

e ||.

In ogni caso, se si tratta di uno di questi due casi, posizionando la freccia del mouse sopra

quel trattino si aprirà una finestra gialla con un pulsante “Fix”. Basterà cliccare su quel e

Matlab automaticamente rimedierà all’errore, ovvero aggiungerà il “;” (se fosse questa la

causa dell’errore). Dovrete ripetere questa operazione per ogni riga che vi segna con un

trattino arancione.

Trucchetto:

Se proprio non capite dove dovete inserire i “;”, potreste anche non metterli mai e poi

inserirli tutti correggendo i vari trattini arancioni che vi compaiono.

- Avere un buon metodo per analizzare il proprio programma:

A volte per compilare un programma è meglio buttare giù le prime idee che ci vengono in

mente, risolvere uno alla volta i problemi che si presentano e cercare quei problemi che

possono capitare solo in determinati casi particolari (quelli più ostici). La cosa più importante

a cui dobbiamo stare attenti mentre scriviamo un programma è sapere sempre cosa abbiamo

scritto. Non è banale come sembra, il più delle volte siamo annebbiati dal fatto che siamo

sicuri che quello che scriviamo sia un codice funzionante al 100%: in realtà raramente un

programma esce perfetto e funzionante alla prima a chiunque, semplicemente la bravura sta

34

nel sapere già come fare a trovare e risolvere il problema che inizialmente ci era sfuggito. È

più facile di quel che sembra:

1) Prima di tutto dobbiamo fare un controllo veloce perché magari si tratta di un semplice

errore di sintassi; per farlo quindi esaminiamo a grandi linee il programma e controlliamo

eventuali errori apparsi nella command window.

2) Se non troviamo nulla dobbiamo provare con un metodo più lento ma attento ai dettagli.

Secondo me il migliore consiste nel prendere carta e penna e fare la simulazione del

programma, scrivendo tutte le variabili con il loro valori ogni volta che se ne incontra una e

modificandoli ogni volta che si modificano anche nei programmi. Per velocizzare l’operazione,

se sono presenti matrici o vettori di grandi dimensioni e di conseguenza anche cicli che

compiono molti giri, il più delle volte basta compiere i primi giri e l’ultimo, oppure considerare

temporaneamente per convenienza una matrice o un vettore di dimensioni più piccole.

3) Alternativamente al metodo carta e

penna possiamo sfruttare la sua

controparte digitale: Matlab infatti ci

fornisce uno strumento fatto apposta

per velocizzare il metodo spiegato

prima, i breakpoints. I breakpoints non

sono altro che dei segnalini che possono

essere inseriti in ogni riga del

programma per fare in modo che il

programma si fermi ogni volta che passa

da quella riga. Per inserire un breakpoint

bisogna cliccare una volta sul trattino

all’inizio della riga scelta e a destra del

numero che la identifica (il pallino rosso

nella riga 7 dell’immagine qua a destra

rappresenta il breakpoint).

Una volta inserito il breakpoint e fatto

partire il programma con run, il

programma si fermerà in quella riga

finchè non premeremo il nuovo tasto

Continue comparso al posto del tasto

run. Per uscire da questa “modalità”

dobbiamo premere sul tasto Quit

Debugging che si trova a destra nella

stessa barra del tasto Continue.

Il miglior modo per usare i breakpoint di solito sta nell’inserirli nella riga dell’end del ciclo più

interno, ma non è l’unico modo; a volte può essere necessario anche inserirne altri nelle righe

di altri passaggi intermedi. In generale potete spostarli, toglierli e metterne di nuovi quando

volete, quindi provate finchè non trovate le posizioni giuste per poter esaminare attentamente

il programma. Come dicevo prima però generalmente conviene metterli negli end, soprattutto

in quello del ciclo più interno: questo perché almeno possiamo fare ogni giro del ciclo che girà

più velocemente. Una volta posizionati per bene i breakpoint, cosa dobbiamo controllare?

Abbiamo già visto l’importanza della command window, ora però è giunto il momento di

imparare ad utilizzare anche il workspace. Questa finestra che di solito si trova in basso a

sinistra o nella parte destra di Matlab immagazzina tutte le variabili del nostro programma 35

con i loro relativi valori assunti quando il programma si ferma. Di conseguenza senza

breakpoint, i valori assunti dalle variabili nel workspace sono quelli che hanno assunto alla

fine del programma; invece mettendo dei breakpoint nel workspace compariranno i valori

delle variabili assunti nella riga sopra a quella dove si trova il breakpoint (la riga dove

compare la freccia verde, che è la solita del breakpoint, viene eseguita alla

ripartenza). Per questo motivo conviene mettere i breakpoint nell’end del ciclo più interno o di

tutti i cicli, perché almeno possiamo vedere che valori assumono le variabili ad ogni giro e

trovare valori sospetti. Ovviamente come prima, se avete a che fare con matrici e vettori di

grandi dimensioni, se non notate niente di strano potete premere il tasto Continue molto

rapidamente nei valori intermedi.

Nota: per vedere i valori assunti da vettori o matrici di grandi dimensioni, dove al posto dei

valori nella colonna Value appare una scritta blu “n m double”, basta cliccare due volte con il

x

tasto sinistro del mouse su questa scritta e si aprirà una nuova finestra simile ad un foglio di

excel dove possiamo vedere tutti i valori del vettore o della matrice. Per tornare nella pagina

nome_del_programma.m

dell’editor basta cliccare nella barra: editor –

4) Ora sicuramente dovreste essere riusciti a scovare quasi tutti gli errori: non rimane altro

che cercare i peli nell’uovo. Già così molto probabilmente il vostro programma sarà valutato

benissimo ma per essere sicuri di aver fatto un ottimo programma dovete provare ad

ingegnarvi e capire con fantasia se esistono casi particolari che potrebbero causare quei

problemi che non capitano con tutti i valori. Se i valori di qualche variabile sono dati da input,

provate a eseguire il programma con molti valori per cercare di trovarne eventuali che creino

problemi; se invece sono generati casualmente, eseguite il programma minimo 20 volte. Se

come succede spesso il vostro programma dovrebbe stamparvi a schermo un messaggio

oppure un altro e le probabilità che ne esca uno o l’altro sono circa del 50% ma quando lo

eseguite vi esce fuori sempre o quasi sempre solo uno dei due vuol dire che c’è un problema.

Prendiamo come esempio il compito del 15/09/2017 svolto prima: ogni giorno, per 200 giorni,

10 camion possono prelevare da 0 a 40 tonnellate di terra, quindi i casi limiti sono o che tutti i

36

camion prelevino 0 tonnellate o che ne prelevano 40*10*200 = 80000. Quindi c’è più o meno

il 50% di possibilità che il limite di tonnellate prefissato a 40000 tonnellate venga superato e

che di conseguenza anche quello dei giorni. 37

Soluzioni esercitazioni:

Ho inserito le soluzioni delle esercitazioni alla fine perché reputo sia più proficuo imparare

direttamente dai compiti precedenti: infatti, nonostante questi abbiano domande e temi

differenti, hanno anche molti elementi in comune come la struttura di base del programma

(si tratta sempre di programmi con almeno due cicli di cui almeno uno solitamente è un while

e dove vi si chiede di lavorare con almeno una variabile, un vettore o con una matrice di

numeri casuali). Invece le esercitazioni tendono ad andare nello specifico di qualsiasi

argomento trattato, portando a volte al limite questi concetti, inutilmente.

Il mio consiglio è quindi quello di cercare prima di analizzare per bene i compiti precedenti,

così da riuscire quasi sicuramente a scrivere almeno la base del programma del vostro

compito; successivamente provare a cimentarsi nelle esercitazioni perché, nonostante più

della metà delle domande che ci troverete non vi capiteranno mai, sono un ottimo

allenamento per comprendere quali sono i ragionamenti che uno deve fare per risolvere un

problema di informatica.

Es: 2.1

clear

%1)

A=[2,4;-1,0.4;-1.5,0];

B=[1,-4,5];

%2)

C=A(1,2);

%3)

D=B(2);

%4)

A(:,2)=B';

%5)

A(3,:)=A(3,:)+5;

%6)

E=[A(:,2),A(:,1)];

%7)

E(2,:)=[];

Es:2.2

clear

%1)

A=rand(4,7);

%2)

B=max(A); % Restituisce un vettore di 7 caselle (numero delle colonne di A)

%dove in ogni sua casella i-esima c'è il valore massimo dell'i-esima

%colonna di A.

B=max(A(:,[1 4])); %A(:,[1 4]) è una matrice composta dalla prima e quarta

%colonna di A. Se uso max su di essa mi restituisce un vettore di lunghezza

%due (perchè la matrice che gli do in pasto ha due colonne) con il massimo

%della prima e della quarta colonna.

B=max(A(:,[1 4])'); %Devo quindi aggiungere ' per considerare la trasposta

%ed ottenere così un vettore lungo 4 con i massimi di ogni riga.

%3)

C=A(1:2,1:3)

%4)

%?

%5)

%?

%6)

F=sum(sum(C));

Es: 2.3

clear

%1) 38

A=[2,4;-1,0.4;-1.5,0];

B=[1,-4,5];

%2)

C=[[B;A']'];

%3)

D=sum(C(1:2,:)).*(A(:,2)');

%4)

A=C'.*C

%5)

C(2,3)=A(2,1)-B(1);

C(3,2)=A(2,3)-B(3);

%6)

A=A+eye(3)*5;

Es: 2.4

clear

%1)

A=[2,4;-1,0.4;-1.5,0];

B=[1,-4,5];

%2)

C=[[B;A']'];

%3)

D=sum(C(1:2,:)).*(A(:,2)');

%4)

A=C'.*C

%5)

C(2,3)=A(2,1)-B(1);

C(3,2)=A(2,3)-B(3);

%6)

A=A+eye(3)*5;

Es: 2.1 seconda parte

clear

%1)

N=fix(rand()*11)+1;

%2)

M=fix(rand(N)*N)+1;

%3)

S=sum(diag(M));

Es: 2.2 seconda parte

clear

%1)

N=fix(rand()*12)+1;

%2)

M=fix(rand(N)*((N^3)-N+1))+N;

%3)

somma=sum(sum(M))-sum(sum(M(2:N-1,2:N-1)));

Es: 2.3 seconda parte

clear

%1)

N=fix(rand()*7)+2;

%2)

K=2^N;

V=rand(1,K)*(N-1)+1;

%3)

S=sum(V);

%4)

if S<128

disp('La somma calcolata non supera il valore 128');

else disp('La somma calcolata supera o è uguale il valore 128');

end 39

Es: 2.4 seconda parte

clear

%1)

M=fix(rand()*8)+1; % li prendo maggiori di 0 perchè non ha senso un vettore di

lunghezza 0 (vedi punto 2)

N=fix(rand()*4)+1;

%2)

K1=2*M;

K2=2*N;

V1=fix(rand(1,K1)*10)+1;

V2=fix(rand(1,K2)*10)+1;

%3)

F1=sum(factorial(V1));

F2=sum(factorial(V2));

%4)

disp(max([F1 F2]));

Es: 2.5 seconda parte

clear

%1)

N=fix(rand()*101)+100;

V1=cos(0:pi/(N-1):pi); %in alternativa: V1=cos(linspace(0,pi,N))

%2)

V2=sin(0:pi/(N-1):pi);

%3)

plot(V1);

hold on;

plot(V2);

%4)

W1=rand(1,N)*0.1;

W2=rand(1,N)*0.1;

Es: 2.6 seconda parte

clear

%1)

H=fix(rand(10)*100)+1;

%2)

Z=zeros(10);

Z(4:7,4:7)=H(4:7,4:7);

%3)

S=sum(sum(H-Z));

%4)

Z=ones(10)*S;

Z(4:7,4:7)=H(4:7,4:7);

disp(Z);

Es: 2.7 seconda parte

clear

%1)

y=sin(linspace(0,pi,1000));

w=cos(linspace(0,pi,50));

%2)

q=y(1:(1000/50):1000)-w;

%3)

%??

Es: 3.1

clear

%1)

V=zeros(1,20); %-

for i=1:20 %- Alternativa:

V(i)=sin(i); %- V=sin(1:20); 40

end %-

%2)

for i=1:20

if V(i)<0.1

V(i)=0;

end

end

%3)

for i=1:20

disp(V(i));

end

Es: 3.2

clear

%1)

N=input('Inserisci la dimensione N della matrice quadrata A: ')

A=zeros(N);

%2)

for i=1:N

A(i,i)=5;

end

%3)

for i=2:N

A(i,i-1)=5-i+1;

end

%4)

for j=2:N

A(j-1,j)=5+j;

end

Es: 3.3

clear

%1)

V(1)=1;

V(2)=1;

for i=3:20

V(i)=V(i-1)+V(i-2);

end

%2)

W(1)=1;

for i=2:10

W(i)=V(i)*V(i)+V(i-1)*V(i-1);

end

%3)

for i=2:2:20

V(i-1)=V(i-1)-W(i/2);

end

Es: 3.4

clear

sm=0; %Punteggio Mario

sl=0; %Punteggio Luigi

k=0; %Numero di volte che Mario raddoppia

j=0; %Numero di volte che Luigi fa lo stesso punteggio

for i=1:100

m=fix(rand(1,2)*6)+1;

l=fix(rand(1,2)*9)+1;

if m(1)==m(2)

sm=sm+4*m(1);

k=k+1;

else sm=sm+m(1)+m(2);

end

if l(1)==l(2)

sl=sl+l(1);

j=j+1;


ACQUISTATO

1 volte

PAGINE

47

PESO

376.64 KB

PUBBLICATO

7 mesi fa


DESCRIZIONE APPUNTO

Dispensa ben organizzata, scritta con un linguaggio comprensibile a tutti, che raccoglie un riassunto della teoria, lo svolgimento guidato di 3 compiti recenti (settembre 2017/febbraio 2018), alcuni consigli personali (esame passato con 30), la spiegazione di alcuni "blocchi di comandi" di base alla programmazione e infine la soluzione di tutti gli esercizi presenti su Moodle. Vi ricordo che tutto il materiale cartaceo può essere portato all'esame, di conseguenza pure tutta questa dispensa.


DETTAGLI
Corso di laurea: Corso di laurea in ingegneria civile
SSD:
Università: Firenze - Unifi
A.A.: 2018-2019

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher fedecoppa97 di informazioni apprese con la frequenza delle lezioni di Grafica computazionale e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Firenze - Unifi o del prof Carfagni Monica.

Acquista con carta o conto PayPal

Scarica il file tutte le volte che vuoi

Paga con un conto PayPal per usufruire della garanzia Soddisfatto o rimborsato

Recensioni
Ti è piaciuto questo appunto? Valutalo!

Altri appunti di Corso di laurea in ingegneria civile

Tecnologia dei Materiali - CLS - Appunti
Appunto
Calcestruzzo e Acciaio - Tecnologia dei materiali
Appunto
Appunti tecnologia dei materiali - Materiali metallici, acciaio
Appunto
Acustica ambientale - appunti
Appunto