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.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow