Here is my sample code, made to work out how to get a while loop to end when any one of three conditions are satisfied.
I want the code to end when n = 100, but it ends at n = 301. How can I get this to end at n=100?
clear all; close all;
n = 0;
R = 0; A = 0; T = 0;
while (R~=1) || (A~=1) || (T~=1)
if n == 100
R = 1;
end
if n == 200
A = 1;
end
if n == 300
T = 1;
end
n=n+1;
end
|| means or (with short circuiting). This means that your loop won't quit until all of the conditions are false.
You want to use AND, which is &&. This will mean the loop quits when at least one of the conditions is false.
ALSO (from the comments below):
Currently n will have a value of 101 when the loop finishes (because of the n=n+1 at the bottom of the loop). If it was important that the value of n was 100, then you could insert a break (info here) into the if body so that the loop quit when n = 100.
Related
The code segment I'm working on is given below:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
while i <= 10 %number of iterations
ind = randi([1 NphaseSteps],10,10);
inField{i} = phases(ind);
save('inField.mat', 'inField')
i = i + 1;
end
Now, what I want is to keep track of these randomly created matrices "inField{i}" and eliminate the ones that are equal to each other. I know that I can use "if" condition but since I'm new to programming I don't know how to use it more efficiently so that it doesn't take too much time. So, I need your help for a fast working program that does the job. Thanks in advance.
My actual code segment (after making the changes suggested by #bisherbas) is the following. Note that I actually want to use the variable "inField" inside the loop for every random created matrix and the loop advances only if the result satisfies a specific condition. So, I think the answer given by #bisherbas doesn't really eliminate the equal inField matrices before they are used in the calculation. This is, of course, my fault since I didn't declare that in the beginning.
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
nIterations = 5;
inField = cell(1,nIterations);
i = 1;
j = 1;
while i <= nIterations % number of iterations
ind = randi([1 NphaseSteps],TMsize,TMsize);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
j = j+1;
outField{i} = TM * inField{i};
outI = abs(outField{i}).^2;
targetIafter{i} = abs(outField{i}(focusX,focusY)).^2;
middleI = targetIafter{i} / 2;
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
if mod(j-1,10^6) == 0
fprintf('The number of random matrices tried is: %d million \n',(j-1)/10^6)
end
end
Additionally, I've written a seemingly long expression for my loop condition:
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
Here I want a maximum element at some point (focusX, focusY) in the outField matrix. So the first condition decides whether the focus point has the maximum element for the matrix. But I additionally want all other elements to be smaller than a specific number (middleI) and that's why the second part of the if condition is written. However, I'm not very comfortable with this second condition and I'm open to any helps.
Try this:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
inField = cell(1,NphaseSteps);
while i <= NphaseSteps %number of iterations
ind = randi([1 NphaseSteps],NphaseSteps,NphaseSteps);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
save('inField.mat', 'inField')
i = i + 1;
end
Read more on cellfun here:
https://www.mathworks.com/help/matlab/ref/cellfun.html
I have a short (and I reckon silly as well) question about manipulation of variables in Matlab codes. How can I keep a constant value of a variable (assigned during the execution of the code), while the code executes further? So basically put the value into the memory and don't change it all. As an example of the code on which I am working right now:
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
Offset = k;
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
So I am looking for an option, how I can keep the calculated value of "Offset" when I got "HmSpeedReached =1". Since we have a "for" cycle in the beginning (that will assign a value to K and then to Offset), so I just need to keep that number as a value of the variable all the time, after the condition of HmSpeedReached is satisfied...
Thank you in advance.
If I understand correctly then you want the following:
Keep assigning Offset = k whilst looping through your code
If HmSpeedReached = 1 has been set, then don't change the Offset value
This code (adapted from yours) should work
% Initially make sure HmSpeedReached is not equal to 1
HmSpeedReached = 0;
% Your code with addition...
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
% Add a condition here to check if Offset should be updated, if HmSpeedReached is not 1
if HmSpeedReached ~= 1
Offset = k;
end
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
If instead you want to save a vector of Offset values, every time some condition is met, then use something like this:
Offset = [];
HmSpeedReached = 0;
if SystemTriggered ==1;
if Accelerationflag == 1;
for n = 1:1:100
AOrder = 1/2*HMSpeed^2/(Acc+n*2*pi);
if AOrder<Alim;
k = n;
Accelerationflag = 0;
break;
end
end
end
% Add a condition here to check if Offset should be updated, if HmSpeedReached is not 1
if CONDITION FOR SAVING OFFSET
Offset = [Offset, k];
end
AccOffset = PhaseIni - Offset*2*pi;
%Derivation conditions
if My condition here;
HmSpeedReached = 1;
end
end
Assign HmSpeedReached = 0 at the top and test for HmSpeedReached equal zero as a condition to change the variable Offset.
I have executed this simple loop script in MATLAB
clc;clear; close all;
m = 100;
for i = 1:m
if(i == 2)
m = 1000;
end
end
and found, that 'i' loops only till '100' BUT NOT '1000'. Why..??
The statement for i=1:m assigns the array 1:m to the list of values the operator will take on during the loop. This happens when the loop starts executing (note: you can use any array, and it'll be worked through column by column; for letter='abcde';fprintf('%s\n',letter);end works fine).
If you want to adjust how often your loop will be iterated through, I recommend using a while loop:
ct = 1;
maxIterations = 100;
success = false;
while ~success
fprintf('iteration %i/%i\n',ct,maxIterations);
ct = ct + 1;
if ct == 2
maxIterations == 1000;
end
if ct > maxIterations
success = true;
end
end
I'm not an expert but the for loop replace the m var with 100 in the first run and then it performs the loop as from 1 to 100 (not 1 to m) and it doesnt check every run what is m it knows that m is 100 and it runs until it reaches 100 if for example your script is like this:
<code>
m=100;
for i=1:m (m is 100)
if(i==2)
m=1000;
for i=1:m (m is 1000)
a=xyz;
end
end
end
</code>
I have a while loop within an else statement. while the condition in the while loop is true I have the variable k decreasing (k=k-1). I want for the while loop to stop before k==0. I have tried placing the while loop within another while loop (while k>1) thinking maybe that would cancel the inner loop if k dropped to 1. Any thoughts?
if yada yada
do thing1
else
while k>1
while x==true
k=k-1;
do thing2
end
end
end
Doesn't this do the trick?
if yada yada
x = f(x) %// If you don't have anything here, you should use "if ~yada yada"
%// instead of "else"
else
while k>1 && x == true %// BTW: Lower case t in true
x = g(y) %// I hope you have something more than "k=k-1" in this loop
k = k-1;
end
end
You could add this sentence to be the last thing on your innermost while
if k <= 1
break;
Since your while-loop is basically achieving a counter-increment, I would highly recommend replacing it (actually, both of them) with a for-loop. In addition to being much more readable, it will allow Matlab to apply optimizations which will result in much faster execution times. See here:
yadayada = false;
x = true;
if yadayada
else
kmax = 5; % or whichever maximum value you want k to have
for k = kmax:-1:2 % have k start at kmax, decrement by 1 each time, until k==2
fprintf('k = %d\n', k);
% do something useful in the loop
if ~x
break;
end
end
end
Output:
k = 5
k = 4
k = 3
k = 2
range = min(x):0.0001:max(x);
N = numel(range);
x = sort(x);
hit = 0;
i=1;
for j = 1:(N-1)
if range(j) <= x(i) && x(i) < range(j+1)
hit = hit + 1;
i = i+1;
if x(i) == x(i-1)
while x(i) == x(i-1) % If there are more than one of the same
hit = hit + 1; % numbers in succession, this allows x and
i = i+1; % hit to carry on incrementing.
end %while
end %if
end %if
end %for
disp(hit)
This code compares 'range' and 'x'. It checks to see if 'x' is between values in 'range', if so the 'hit' counter gets incremented and so does the current value of 'x'.
Problem is, on some random values of x (as far as I can tell they are random), although they should satisfy the inequality in the 'IF' statement, the 'IF' statement gets ignored, the for loop continues and thus the final 'hit' value is wrong.
'x' is usually a 1D array about a million or so wide.
for this example, let
`x = [-2.1792 -2.1759 -2.1758 -2.1748 -2.1658 -2.1648 -2.1646 -2.1604 -2.1603 -2.1550]`
'hit' should equal '10' but instead outputs '2' since it decides to skip the 'IF' statement at 'j=35'.
To clarify. When 'j=35', range(j) = -2.1758 and i=3 meaning x(i)=-2.1758
I'm pretty sure that:
range(j) <= x(i) && x(i) < range(j+1)
-2.1758 <= -2.1758 && -2.1758 < -2.1757 %**edited, meant -2.1757 not -2.1759**
Is true.
I hope I'm just doing something silly here that I can't see. Sorry if it's a badly formatted question, it's my first here.
Cheers in advance.
A subsequent number x(i) could pass this test:
if range(j) <= x(i) && x(i) < range(j+1)
Without actually being equal to its neighbor:
if x(i) == x(i-1)
It could be infinitesimally larger and thus you move to the next j and it is out of range. Your inner while needs the same condition as the outer if. And you can skip the if COND while COND and just do while COND since it will work the same.
Would the following code not be simpler, faster, and give the same result?
x = sort(x)
hit = sum(diff(x)==0);