Only else part is being executed in If-else statement in matlab - matlab

I'm working on counting numbers using if-else statement. I'm getting the result, but it's only executing the else part and not looking at the other part.
This is the code I'm working with
i = 0;
j = 0;
if sum( abs( f1(:) - f2(:))) == 0.0
i = i + 1;
else
j = j + 1;
end
if sum(abs(f2(:) - f3(:))) == 0.0
i = i + 1;
else
j = j + 1;
end
if sum(abs(f3(:) - f4(:))) == 0.0
i = i + 1;
else
j = j + 1;
end
msgtext = sprintf('Matching = %d',i);
h = msgbox(msgtext);
msgtxt = sprintf(' Not Matching = %d',j);
h = msgbox(msgtxt);
Any suggestions?
Thanks in advance!

Your question is extremely vague so I'm going to pretend you only asked about one of the ifs:
if sum( abs( f1(:) - f2(:))) == 0.0
i = i + 1;
else
j = j + 1;
end
I think there is a fair chance that you only ever fall into the else clause because you are trying to equate floating point numbers, and that is a bad idea due to precision errors. This depends on the nature of f1 and f2, are they doubles, how were the calculated etc which you have given no indication of in your question. If you want to understand why you can't equate floating point numbers (or expect there difference to equal 0) then you must read What every computer scientist needs to know about floating-point arithmetic
Rather try if sum( abs( f1(:) - f2(:))) < tol where tol (i.e. tolerance) is a really tiny number (e.g. eps, but just choose a number that is orders of magnitude less than your application could produce.).

Related

MATLAB — How to eliminate equal matrices that are created randomly inside loop?

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

Finding smallest value for parameterised answer that satisfies condition

I want to find the smallest integer l that satisfies l^2 >= x, and mod(l,2)=0.
In the following example x=75, and hence l=10, since the previous even number doesn't fulfil the inequation: 8^2 <= 75 <= 10^2
I have tried this (ignoring the even-number requirement, which I can't to work):
syms l integer
eqn1 = l^2 >= 75;
% eqn2 = mod(l,2) == 0;
[sol_l, param, cond] = solve(eqn1, l, 'ReturnConditions', true);
But this does not give me anything helpful directly:
sol_l =
k
param =
k
cond =
(75^(1/2) <= k | k <= -75^(1/2)) & in(k, 'integer')
I would like to evaluate the conditions on the parameter and find the smallest value that satisfies the conditions.
Also, I would like to enforce the mod(l,2)=0 condition somehow, but I don't seem to get that work.
Using the solve for this task is like using a cannon to kill a mosquito. Actually, the answer of Lidia Parrilla is good and fast, although it can be simplified as follows:
l = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l = l + 1;
end
% if x = 75, then l = 10
But I would like to point out something that no one else noticed. The condition provided by the solve function for l^2 >= 75 is:
75^(1/2) <= k | k <= -75^(1/2)
and it's absolutely correct. Since l is being raised to the power of 2, and since a negative number raised to the power of 2 produces a positive number, the equation will always have two distinct solutions: a negative one and a positive one.
For x = 75, the solutions will be l = 10 and l = -10. So, if you want to find the smallest number (and a negative number is always smaller than a positive one), the right solution will be:
l = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l = l + 1;
end
l = l * -1;
If you want to return both solutions, the result will be:
l_pos = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l_pos = l_pos + 1;
end
l_neg = l_pos * -1;
l = [l_neg l_pos];
I guess the easiest solution without employing the inequality and solve function would be to find the exact solution to your equation l^2 >= x, and then finding the next even integer. The code would look like this:
x = 75;
y = ceil(sqrt(x)); %Ceil finds the next bigger integer
if(~mod(y,2)) %If it's even, we got the solution
sol = y;
else %If not, get the next integer
sol = y+1;
end
The previous code gives the correct solution to the provided example (x = 75; sol = 10)

index must be a positive integer or logical?

k = 0.019;
Pstar = 100;
H = 33;
h = 0.1;
X = 36;
N = round(X/h);
t = zeros(1,N+1);
P = zeros(1,N+1);
P(1) = 84;
t(1) = 0;
yHeun = zeros(1,N+1);
yHeun(1)=84;
a = 1; b = 100;
while b-a >0.5
c = (a+b)/2;
for n = 1:N
t(n+1) = t(n) + h;
Inside = nthroot(sin(2*pi*t/12),15);
Harvest = c*0.5*(Inside+1);
P(n+1) = P(n) + h*(k*P(n)*(Pstar-P(n))-Harvest(n));
if P < 0
P = 0;
end
yHeun(n+1) = yHeun(n) + h*0.5*((k*P(n)*(Pstar-P(n))-Harvest(n))+(k*P(n+1)*(Pstar-P(n+1))-Harvest(n+1)));
end
if sign(yHeun(c)) == sign(yHeun(a))
c = a;
else
c = b;
end
end
disp(['The root is between ' num2str(a) ' and ' num2str(b) '.'])
This is the code i'm trying to run and i know it probably sucks but im terrible at coding and every time i try to run the code, it says:
Attempted to access yHeun(50.5); index must be a positive integer or
logical.
Error in Matlab3Q4 (line 30)
if sign(yHeun(c)) == sign(yHeun(a))
I don't have ANY idea how to make yHeun(c or a or whatever) return anything that would be an integer. I dont think i did the while+for loop right either.
Question: "Begin with the higher bound of H being 100 (the high value results in a population of 0 after 36 months), and the lower bound being 1. Put the solver from Problem #3 above in the middle of a while loop and keep bisecting the higher and lower bounds of H until the difference between the higher and lower bound is less than 0.5."
I guess that line 30 (with the error) is this one:
if sign(yHeun(c)) == sign(yHeun(a))
Here, I guess c is equal to 50.5, as a result of c = (a+b)/2 above (BTW you can discover whether I guessed right by debugging - try adding disp(c) before line 30).
To force a number to be an integer, use floor:
c = floor((a+b)/2);
It seems you are trying to use some sort of divide-and-conquer algorithm; it should be enough to stop when b - a is equal to 1.

Matlab error : Subscript indices must either be real positive integers or logicals

I have the following error in MATLAB:
??? Subscript indices must either be real positive integers or
logicals.
Error in ==> Lloyd_Max at 74 D(w_count) = mean((x -
centers(xq)).^2);
This is my code :
function [ xq,centers,D ] = Lloyd_Max( x,N,min_value,max_value )
%LLOYD_MAX Summary of this function goes here
% Detailed explanation goes here
x = x';
temp = (max_value - min_value)/2^N;
count=1;
for j=0:temp:((max_value - min_value)-temp),
centers(count) = (j + j + temp )/2;
count = count + 1;
end
for i=1:length(centers),
k(i) = centers(i);
end
w_count = 0;
while((w_count < 2) || (D(w_count) - D(w_count - 1) > 1e-6))
w_count = w_count + 1;
count1 = 2;
for i=2:(count-1),
T(i) = (k(i-1) + k(i))/2;
count1 = count1 +1 ;
end
T(1) = min_value;
T(count1) = max_value;
index = 1;
for j=2:count1,
tempc = 0;
tempk = 0;
for k=1:10000,
if(x(k) >= T(j-1) && x(k) < T(j))
tempk = tempk + x(k);
tempc = tempc + 1;
end
end
k(index) = tempk;
k_count(index) = tempc;
index = index + 1;
end
for i=1:length(k),
k(i) = k(i)/k_count(i);
end
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
for i=1:10000,
cnt = 1;
for l=2:count1,
if(xq(i) > T(l-1) && xq(i) <= T(l))
xq(i) = cnt;
end
cnt = cnt +1 ;
end
end
D(w_count) = mean((x - centers(xq)).^2);
end
end
and i call it and have these inputs :
M = 10000
t=(randn(M,1)+sqrt(-1)*randn(M,1))./sqrt(2);
A= abs(t).^2;
[xq,centers,D] = Lloyd_Max( A,2,0,4 );
I tried to comment the while and the D, Results :
I got the xq and the centers all normal, xq in the 1-4 range, centers 1-4 indexes and 0.5-3.5 range.
I dont know whats going wrong here...Please help me.
Thank in advance!
MYSTERY SOVLED!
Thank you all guys for your help!
I just putted out of the while the for loop :
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
and it worked like charm.... this loop was initilizing the array again. Sorry for that. Thank you again!
There is an assignment xq(i) = x(i) somewhere in the middle of your function, but you pass A as x from outside where you calculate A from t which is sampled by randn, so you can't promise xq is an integer.
I'm not sure exactly what you are aiming to do, but your vector xq does not contain integers, it contains doubles. If you want to use a vector of indices as you do with centers(xq), all elements of the vector need to be integers.
Upon a little inspection, it looks like xq are x values, you should find some way to map them to the integer of the closest cell to which they belong (i'm guessing 'centers' represents centers of cells?)

How to correct " Subscript indices must either be real positive integers or logicals." in Matlab in my code?

I am very new in Matlab. I made a for loop with i to m ,and j to n. I wrote this code to take a submatrix of a matrix but it keeps giving me this error
Subscript indices must either be real positive integers or logicals.
this is the code
for i=1:m,
for j = 1:n,
display(i);
display(j);
edgeil = 2;
edgeib = 2;
edgejb = 2;
edgejl = 2;
if((i-CenteriSE)< 0)
edgeib = CenteriSE - (-1)*(i-CenteriSE);
end
if((i+ CenteriSE)> m)
temp = i+ CenteriSE - m;
edgeil = CenteriSE - temp;
end
if((j-CenterjSE)< 0)
edgejb = CenterjSE- (-1)*(j-CenterjSE);
end
if((j+ CenterjSE)> n)
temp2 = j+ CenterjSE - n;
edgejl = CenterjSE - temp2;
end
bok1 = round(edgeib);
bok2 = round(edgeil);
bok3 = round(edgejb);
bok4 = round(edgejl);
display(bok1);
display(bok2);
if( (bok1 == round(bok1)) && (bok2 == round(bok2)) && (bok3 == round(bok3)) && (bok4 == round(bok4)))
B = circles(i-round(bok1):i+round(bok2),j-round(bok3):j+round(bok4));
end
I wrote that if statement and round s to correct it but it doesnt work. Please help me how can I fix this?
well, it's simple. first let's just remove all the clutter. you say CenteriSE=2, so this statement
edgeib = CenteriSE - (-1)*(i-CenteriSE); is equivalent to edgeib=i for i=1.
Now if you go to your last statement, B = circles(i-round(bok1):i+round(bok2),j-round(bok3):j+round(bok4));, you're doing i-round(bok1), which is just i-i=0 when i=1. Matlab's indexing start from 1, and this is why you get this error.