My code works when I type
if size(k)==size(k1)
disp('They match');
end
or
if k-k1==0
disp('They match');
end
but if I type in two conditions at the same time like this,
if size(k)==size(k1) & k-k1==0
disp('They match');
end
I get an error saying
Matrix dimensions must agree.
Error in practice (line 32) if size(k)==size(k1) & k-k1==0
FYI, the dimension of k and k1 are both 1x717 double. I checked it.
So I want to make an if statement that includes two conditions at the same time, but I am experiencing an error. Two && won't work cuz two && is for scalars, but my k and k1 are vectors.
Any help will be appreciated
when you compare two vectors the result would be also a vector (a logical vector), but an if condition accept scalar logical values, so you can use all function.
if all(size(k)-size(k1)==0) && all(k-k1==0)
disp('They match');
end
You should always use && in a loop, '&' is used only for logical operation AND.
I have tested this and it works:
k = rand(1,10);
k1 = k;
if all(size(k)-size(k1)==0) && all(k-k1==0)
disp('They match');
end
because when you do this:
>> k-k1==0
ans =
1×10 logical array
1 1 1 1 1 1 1 1 1 1
So the if does not know which value to refer to. But when you do
>> all(k-k1==0)
ans =
logical
1
It gives a unique answer for all the elements of the vector.
Important Note:
Comparing numbers is not a good idea for making decisions on the loops, because of the Floating Point Error problem.
A Better War to Handle it
If you read about the floating point error problem, you will see that sometimes,
2.000 == 2.000 results to false. In order to fix that you can do as follows:
tolerance = 0.0001;
if all(size(k)-size(k1)==0) && all(abs(k-k1)<=tolerance)
disp('They match');
end
You first define an acceptable tolerance value depending on the nature of the problem you are trying to solve and then instead of comparing the subtract to zero, you compare the absolute value of the abstract to the tolerance. Thus, the numbers such as 23.0001 and 23.000 would be considered equal.
The problem is size(k) and size(k1) returns 1*2 vectors (number of rows and columns), so size(k)==size(k1) returns two values. On the other hand k-k1==0 returns only logical matrix with same dimension as k & k1.
For example, if k == k1, you would expect both to be equal.
size(k)==size(k1) % returns 1 1
k == k1 % returns 1
if [1 1] && 1 % gives erros
Alternatively, use isequal which will not give error even if dimensions not matching.
isequal(k,k1) % returns 1 if equal, 0 otherwise.
Related
I have a matrix being created in MATLAB but need to check if any two consecutive numbers (by row) = 0 and if it does output with a yes or no without showing the answers. Ive put my code below my final loop is returning errors and im not too sure how to go about this.
%%Input positive integer
n=input('Give a positive integer greater than 1: ');
%%Error for below 1
if n<=1
error('The value given is less than or equal to 1')
end
%%loop for vector v
for i=1:n
v(i)=2^i*3;
end
%display vector
v
A=randi([-5,5],n,n);
A
x = 1;
consecutive = false;
for i = 1:25
if (A(x) + A(x+1) = 0);
consecutive = true;
end
end
There's a lot wrong with the code of your final loop:
You set x to 1 and use it as an index into A, but never change it from 1.
As Amit points out, you are using = (used for assignment) when you should be using == (the equality operator).
As Gondrian points out, you are testing if a sum is equal to zero, but from your description it sounds like you should be testing if each value is zero.
Your loop iterates 25 times (i = 1:25), but it's not clear why, since your matrix A is of size n-by-n.
Instead of using a for loop, it's possible to do this with indexing instead. Since you are checking for consecutive zeroes by row, this is what it would look like:
zeroPairs = (A(:, 1:(n-1)) == 0) & (A(:, 2:n) == 0);
consecutive = any(zeroPairs(:));
The term A(:, 1:(n-1)) gets all of the "left" values in each pairwise comparison and the term A(:, 2:n) gets all of the "right" value. These are compared to 0, then combined. This creates an n-by-(n-1) matrix zeroPairs where a value of true indicates where a pair of consecutive zeroes occurs. This matrix is reshaped into a column vector and any is used to check if a value of true is present anywhere.
You will need to change your if block as follows.
if (A(x) + A(x+1) == 0);
consecutive = true;
end
Notice the == instead of just =. The first one is for comparison and the second one is for assignment. This will get rid of the error that you are currently getting. There may be other issues in the algorithm of your code but I did not examine or try to fix that.
btw:
'if any two consecutive numbers (by row) = 0'
If I understand you right, you should try 'if A(x) == 0 && A(x+1) == 0';
because '(A(x) + A(x+1) == 0)' would be true for -5 and 5, as it equals to 0. But -5 and 5 are not two consecutive zeros.
(or even look at the 'diff' function. It will return a 0 if two following numbers are the same)
To show a vectorized, more Matlab-like approach:
v = 0; % sought value
C = 2; % desired number of consecutive values in a row
consecutive = nnz(conv2(double(A==v), ones(1,C))==C)>0;
This compares each entry of A with the value v, and then applies 2D convolution with a row vector of C ones. Any C horizontally-consecutive entries of A with value v will produce an entry equal to C in the convolution result. So we check if the number of such entries is positive.
for i = 1:6
if data(i,1) == 1
disp(i)
m(i,:) = data(i,:)
end
end
The code above returns a matrix m, with rows of data from the data file.
However, data(i,1) == 1 is true 4 times for the particular data, however m has 6 rows. 2 of the rows of m are just full of 0's, but the if statement is only true 4 times.
Why is that happening?
In answer to "why is that happening", it is because your matrices are the same size, but you only assign values to the rows which satisfy a condition. Therefore leaving other rows as 0s.
You either need a way to build m row by row (see end of this post) or create it in another way (my answer).
You can do this with logical indexing
% For creating m
m = data(data(:, 1) == 1, :);
% For displaying which indices satisfy your condition, one call to disp
disp( find(data(:, 1) == 1) )
Breaking this down, m is assigned to the values of data, where the column 1 of data is equal to 1, and all of the columns.
find returns the index of any non-zero element. The logical indexing returns an array of 0s and 1s, so all elements which satisfy the condition (and are 1) will be indexed by find.
You could also create the logical index and use it twice, better for maintenance at a later date if your condition changes:
% create logical index
idx = ( data(:,1) == 1 );
% same as above but using idx
m = data(idx, :);
disp( find(idx) )
Documentation
Logical indexing - https://uk.mathworks.com/help/matlab/matlab_prog/find-array-elements-that-meet-a-condition.html
find - https://uk.mathworks.com/help/matlab/ref/find.html
#Ander's suggestion to append only certain rows will work, and demonstrates well how to build a matrix. However, in this case you do not need your loop and if condition at all.
This is standard MATLAB.
Lets assume data(1,1) and data(3,1) are 1.
Then m(1,:)=data(1,:) and later m(3,:)=data(3,:). But what about m(2,:) It has to exist, because you filled m(3,:). There is no 3 without 2!
If you want m to have only the ones where data(i,1) == 1 then do:
m=[]; %create empty matrix
for i = 1:6
if data(i,1) == 1
disp(i)
m= [m; data(i,:)]; % "append" to m
end
end
I have a cell described as the following:
mixed_values = {'jim', 89, [5 2 1; 1 2 3]};
mixed_values{1}
mixed_values{2}
mixed_values{3}
I loop it:
for k=1:length(mixed_values)
curstate=mixed_values{k};
% Check for the [5 2 1; 1 2 3]
if ismatrix(curstate)
disp('yes');
else
disp('no')
end
end
But it founds the matrix multiple times.
yes
yes
yes
How to check it by the way?
From Matlab help:
ismatrix(M) returns logical 1 (true) if SIZE(M) returns [m n] with
nonnegative integer values m and n, and logical 0 (false) otherwise
so I checked size(curstate)
1 3 % 3 character string array
1 1 % of course you can do size of a single elements
2 3
so I modified your code
for k=1:length(mixed_values)
curstate=mixed_values{k};
% Check for the [5 2 1; 1 2 3]
if (size(curstate,1)) > 1 && (size(curstate,2)) > 1
disp('yes');
disp(size(curstate));
else
disp('no')
end
end
It really depends on what you define a matrix to be. In MathWorks case they decided that a matrix would be something with a valid size, which is certainly true. Notice that even scalars are matrices, of size 1x1. You can even have a matrix of characters. A = ['a' 'b';'c' 'd'];. I gather that in your case you want a matrix to be a numerical collection of at least 2 dimensions. I would solve it this way:
function result = TestForMatrix(m)
t1 = isnumeric(m);
t2 = ~isvector(m);
result = all([t1 t2]);
end
Use it as if it was ismatrix.
if (TestForMatrix(curstate))
disp('yes');
else
....
The way this works is the test for numerical numbers will eliminate character strings. The second test will eliminate vectors and scalars. As you find more things to include or eliminate you add those tests. For example, say you want to allow cells. t3 = iscell(m); result = all([t1 t2 t3]); The are many logical tests that can be done on Matlab objects, see Matlab is*.
I have an array in Matlab called myVec and I have to execute an operation if the array contains at least one 1 and one 0.
I do not know how I could do that, I tried with find but it did not work.
This is what I need.
if %myVec contains 0 && myVec contains 1
%Code A
else
%Code B
end
I checked that if you try for example find(myVec==0)and it returned the positions which fulfill the statement, it could be used as a boolean if find(myVec==0) but then I tried if (find(myVec==0) && find(myVec==1)) and The following error is shown Operands to the || and && operators must be convertible to logical scalar values.
Thank you everyone.
if sum(myVec==1) && sum(myVec==0)
%Code A
else
%Code B
end
% sum(myVec==1) counts the number of ones in myVec
% sum(myVec==0) counts the number of zeros in myVec
% if myVec is a matrix with more than one rows and columns, use myVec(:) instead
I am new in matlab coming from c++ and trying to do 2d convolution. I have done dry run but nothing seems to go wrong but i dont know why this coming
My simple logic if value is lesser equal to zero then place zero. I am using this expression for solving that problem
i am facing 2 errors at
1)at f(q,p)=zeros(q,p);
2) at output_args(x,y)=output_args(x,y) + (W(s, t)* f(q,p));
function output_args = convo(img,k )
//skipped the portion of code---
z=s;i=t;
for x=1:row
for y=1:col
for s=s:a+2
% disp(s);
for t= t:b+2
q=z-s;
p=i-t;
if q<=0
if p <=0
f(q,p)=0; %// trying to place zero at index so help needed which is 1st error i have said
end
end
% disp(f(q,p));
output_args(x,y)=output_args(x,y) + (W(s, t)* f(q,p)); %//2nd error is comin (as i have told you above.
end
end
w=w+1;
end
z=z+1;
end
end
at console:(error occur when i apply
1) Subscript indices must either be real positive integers or logicals at f(q,p)=0
2) Attempted to access f(0,0); index must be a positive integer or logical. output_args(x,y)=output_args(x,y) + (W(s, t)* f(q,p));
so any idea?
if q<=0
if p <=0
f(q,p)=0; % p and q will always be invalid!
end
end
Well, that is begging for that error. In MATLAB, Indices must be greater than zero. While you can invert the if-condition to ensure that the index is positive, that will change the mending of your code.
if q > 0
if p > 0
f(q,p)=0; % p and q will always be valid.
end
end
If you need to index from -5 to 5 (for example) you could instead index from 1 to 11 instead. Just remember that you subtract 6 every time you display values. Alternatively, store the "real" indices in another vector.