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
Related
I am new to Julia. A was curious how do I append values. I want b to grow every time the boolian value is True. And then to output its size.
function f(img_deformed, img)
s = size(img)[1]
for i in range(1,s,step=1)
for j in range(1,s,step=1)
b = img_deformed[i,j] == img[i,j]
end
end
return b
end
If you want b to be a vector that tracks the number of times that the equality in your for loop is satisfied, you can use push!:
function f(img_deformed, img)
s = size(img)[1]
b = Vector{Bool}() # Can also use Bool[]
for i in range(1,s,step=1)
for j in range(1,s,step=1)
if img_deformed[i,j] == img[i,j]
push!(b, true)
end
end
end
return length(b)
end
However, if all you really care about is the number of trues, it's easier (and almost certainly better) to just use b as a counter:
function f(img_deformed, img)
s = size(img)[1]
b = 0
for i in range(1,s,step=1)
for j in range(1,s,step=1)
if img_deformed[i,j] == img[i,j]
b += 1
end
end
end
return b
end
Some minor style points: s = size(img)[1] is equivalent to s = size(img, 1), and the range(1, s, step=1) is equivalent to 1:s, so your code could be written slightly more simply as
function f(img_deformed, img)
s = size(img, 1)
b = 0
r = 1:s
for i in r
for j in r
if img_deformed[i,j] == img[i,j]
b += 1
end
end
end
return b
end
However, that doesn't address a potential mistake in the original code: unless you know that img will always be a square matrix, using the same range (1:s) for both for loops is not guaranteed to be correct. To avoid this problem, you can use axes:
function f(img_deformed, img)
b = 0
for j in axes(img, 2)
for i in axes(img, 1)
if img_deformed[i,j] == img[i,j]
b += 1
end
end
end
return b
end
Notice here that I've chosen to loop over the columns first; this is a good practice in Julia, since arrays are stored in column-major order (see the explanation here from the manual).
Note also that using img to control the values that we loop over implicitly assumes that size(img) == size(img_deformed). Without knowing more about what this function is intended for, it's hard to suggest how to deal with that, but if you can assume that the two matrices should be the same size, you can add a check at the top of f(), e.g.
function f(img_deformed, img)
#assert size(img) == size(img_deformed)
# rest of code is the same
end
I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.
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 "triple nested" for loop. I have a continue in my last for loop when it is equal to the first for loop (see code) I've tried to debug the issue in a separate function to see if I was missing something, but the for loop works fine in principle by itself. The issue is that when run, the continue function jumps out of the current for loop and into the second for loop. I've never seen a continue function do this, and I've tried about everything I can think of to make it right.
Here's the code:
for i = 1:n
acc = 0;
for c = 0:2
disp(i); **<---for loop continues to here instead of in the "j" for loop and going to j = 2**
disp(c);
for j = 1:n
disp(j);
if i == j
continue;
else
if c == 0
acc = acc + (m(j)/r(i,j))*(r0(3*j)-r0(3*i));
else
acc = acc + (m(j)/r(i,j))*(r0((3*(j-1))+c)-r0((3*(i-1))+c));
end
end
%multiplying by gravitational constant
acc = G*acc;
%defining velocity in terms of acceleration
if c == 0
dy(3*n+(3*i)) = acc;
else
dy(3*n+(3*(i-1)+c)) = acc;
end
disp(dy)
end
end
end
Here's the output:
n_body
#setup
1
0
1
1
1
1
Appreciate the help.
I have written a function that estimates the inverse of e and loops through values of n until the approximated value is within a given tolerance of the actual value.
Currently I use this code:
function [approx, n] = calc_e(tolerance)
for n = 1:inf
approx = ((1-1/n)^n);
diff = (1/exp(1)) - approx;
if diff < tolerance, break; end
end
end
This works fine however I have been told that it could be more efficient by using a while loop but I can't work out how to do it in that way.
Can anybody shed some light on this?
Simply do:
function [approx, n] = calc_e(tolerance)
n = 1;
while (1/exp(1)) - ((1-1/n)^n) >= tolerance
n = n + 1;
end
end