MATLAB Language
Voor lussen
Zoeken…
Opmerkingen
Herhaal over kolomvector
Een veel voorkomende bron van bugs probeert de elementen van een kolomvector te herhalen. Een kolomvector wordt behandeld als een matrix met één kolom. (Er is eigenlijk geen onderscheid in Matlab.) De for
lus wordt eenmaal uitgevoerd met de lusvariabele ingesteld op de kolom.
% Prints once: [3, 1]
my_vector = [1; 2; 3];
for i = my_vector
display(size(i))
end
De iteratievariabele wijzigen
Het wijzigen van de iteratievariabele verandert de waarde ervan voor de huidige iteratie, maar heeft geen invloed op de waarde in volgende iteraties.
% Prints 1, 2, 3, 4, 5
for i = 1:5
display(i)
i = 5; % Fail at trying to terminate the loop
end
Prestaties in a:b
speciaal geval van a:b
aan de rechterkant
De basisvoorbeeld behandelt 1:n
als normale voorbeeld van het creëren van een rijvector en vervolgens itereren over. Om prestatieredenen behandelt Matlab eigenlijk a:b
of a:c:b
speciaal door de rijvector niet volledig te maken, maar in plaats daarvan elk element één voor één te maken.
Dit kan worden gedetecteerd door de syntaxis enigszins te wijzigen.
% Loops forever
for i = 1:1e50
end
% Crashes immediately
for i = [1:1e50]
end
Lus 1 naar n
Het eenvoudigste geval is gewoon een taak vooraf uitvoeren voor een vast bekend aantal keren. Stel dat we de getallen tussen 1 en n willen weergeven, we kunnen schrijven:
n = 5;
for k = 1:n
display(k)
end
De lus voert de interne bewering (en), alles tussen het for
en het end
, gedurende n
keer uit (5 in dit voorbeeld):
1
2
3
4
5
Hier is nog een voorbeeld:
n = 5;
for k = 1:n
disp(n-k+1:-1:1) % DISP uses more "clean" way to print on the screen
end
deze keer gebruiken we zowel de n
als de k
in de lus om een "genest" scherm te maken:
5 4 3 2 1
4 3 2 1
3 2 1
2 1
1
Herhaal over elementen van vector
De rechterkant van de toewijzing in een for
lus kan elke rijvector zijn. De linkerkant van de toewijzing kan elke geldige variabelenaam zijn. De for
lus wijst elke run een ander element van deze vector toe aan de variabele.
other_row_vector = [4, 3, 5, 1, 2];
for any_name = other_row_vector
display(any_name)
end
De uitvoer zou worden weergegeven
4
3
5
1
2
(De 1:n
versie is hiervan een normaal geval, omdat in Matlab 1:n
slechts syntaxis is voor het construeren van een rijvector van [1, 2, ..., n]
.)
Daarom zijn de volgende twee codeblokken identiek:
A = [1 2 3 4 5];
for x = A
disp(x);
end
en
for x = 1:5
disp(x);
end
En de volgende zijn ook identiek:
A = [1 3 5 7 9];
for x = A
disp(x);
end
en
for x = 1:2:9
disp(x);
end
Elke rijvector volstaat. Het hoeven geen cijfers te zijn.
my_characters = 'abcde';
for my_char = my_characters
disp(my_char)
end
zal uitvoeren
a
b
c
d
e
Herhaal over kolommen van matrix
Als de rechterkant van de toewijzing een matrix is, krijgt de variabele bij elke iteratie opeenvolgende kolommen van deze matrix.
some_matrix = [1, 2, 3; 4, 5, 6]; % 2 by 3 matrix
for some_column = some_matrix
display(some_column)
end
(De rijvector-versie is hiervan een normaal geval, omdat in Matlab een rijvector slechts een matrix is waarvan de kolommen grootte 1 hebben.)
De uitvoer zou worden weergegeven
1
4
2
5
3
6
dat wil zeggen elke weergegeven kolom van de geïtereerde matrix, elke kolom afgedrukt op elke oproep tot display
.
Lus over indexen
my_vector = [0, 2, 1, 3, 9];
for i = 1:numel(my_vector)
my_vector(i) = my_vector(i) + 1;
end
De meeste eenvoudige dingen die met for
loops worden gedaan, kunnen sneller en gemakkelijker worden gedaan door vectorized bewerkingen. De bovenstaande lus kan bijvoorbeeld worden vervangen door my_vector = my_vector + 1
.
Geneste lussen
Lussen kunnen worden genest om een iteratie van een taak binnen een andere iteratie uit te voeren. Overweeg de volgende lussen:
ch = 'abc';
m = 3;
for c = ch
for k = 1:m
disp([c num2str(k)]) % NUM2STR converts the number stored in k to a charachter,
% so it can be concataneted with the letter in c
end
end
we gebruiken 2 iterators om alle combinaties van elementen uit abc
en 1:m
, wat resulteert in:
a1
a2
a3
b1
b2
b3
c1
c2
c3
We kunnen ook geneste lussen gebruiken om te combineren tussen taken die elke keer moeten worden uitgevoerd en taken die een keer in verschillende iteraties moeten worden uitgevoerd:
N = 10;
n = 3;
a1 = 0; % the first element in Fibonacci series
a2 = 1; % the secound element in Fibonacci series
for j = 1:N
for k = 1:n
an = a1 + a2; % compute the next element in Fibonacci series
a1 = a2; % save the previous element for the next iteration
a2 = an; % save ht new element for the next iteration
end
disp(an) % display every n'th element
end
Hier willen we alle Fibonacci-serie berekenen, maar alleen het n
de element elke keer weergeven, dus we krijgen
3
13
55
233
987
4181
17711
75025
317811
1346269
Een ander ding dat we kunnen doen is het gebruik van de eerste (buitenste) iterator in de binnenste lus. Hier is nog een voorbeeld:
N = 12;
gap = [1 2 3 4 6];
for j = gap
for k = 1:j:N
fprintf('%d ',k) % FPRINTF prints the number k proceeding to the next the line
end
fprintf('\n') % go to the next line
end
Deze keer gebruiken we de geneste lus om de uitvoer te formatteren en remmen we de lijn alleen af wanneer een nieuwe opening ( j
) tussen de elementen werd geïntroduceerd. We doorlussen de spleetbreedte in de buitenste lus en gebruiken deze in de binnenste lus om door de vector te lopen:
1 2 3 4 5 6 7 8 9 10 11 12
1 3 5 7 9 11
1 4 7 10
1 5 9
1 7
Opmerking: Raar dezelfde tegengestelde geneste lussen.
Dit zie je niet in andere programmeeromgevingen. Ik kwam het een paar jaar geleden tegen en ik kon niet begrijpen waarom het gebeurde, maar na enige tijd met MATLAB te hebben gewerkt, kon ik erachter komen. Bekijk het codefragment hieronder:
for x = 1:10
for x = 1:10
fprintf('%d,', x);
end
fprintf('\n');
end
je zou niet verwachten dat dit goed werkt, maar dat doet het wel, met de volgende uitvoer:
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
De reden is dat, net als bij al het andere in MATLAB, de x
teller ook een matrix is - een vector om precies te zijn. Als zodanig is x
slechts een verwijzing naar een 'array' (een coherente, opeenvolgende geheugenstructuur) waarnaar op passende wijze wordt verwezen met elke volgende lus (genest of niet). Het feit dat de geneste lus dezelfde identifier gebruikt, maakt niet uit hoe naar waarden uit die array wordt verwezen. Het enige probleem is dat binnen de geneste lus de buitenste x
wordt verborgen door de geneste (lokale) x
en daarom niet kan worden verwezen. De functionaliteit van de geneste lusstructuur blijft echter intact.