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
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.
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.
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*.
For example I want to have a function which let me delete rows of my matrix where the highest value is 1. Thus I wrote:
% A is an input matrix
% pict2 suppose to be output cleared matrix
function pict2 = clear_(A)
B=A
n = size(A,1)
for i=1:n
if(max(B(i,:))==1)
B(i,:)=[]
end
end
But after I call:
pict2=clear_(pict) the Matlab resposes:
"warning: clear_: some elements in list of return values are undefined
warning: called from
clear_ at line 5 column 1 pict2 = "
I'm not sure which elements were left undefined?
The variable name of your output argument must match the variable that you want to be returned. So you'll want to change the first line to the following so that your modifications to B are saved and returned.
function B = clear_(A)
As far as your algorithm is concerned, it's not going to work because you are modifying B while trying to loop through it. Instead, you can replace your entire function with the following expression which computes the maximum value of each row, then determines if this value is equal to 1 and removes the rows where this is the case.
B(max(B, [], 2) == 1, :) == [];
I believe that, alternatively to the suggestions you already recieved, you might want to try the following. Using logicals is probably one of the best options for such a problem, since you don't need to use for-loops:
function out = clear_matr(A)
% ind is true for all the rows of A, where the highest value is not equal to 1
ind = ~(max(A, [], 2) == 1);
% filter A accordingly
out = A(ind, :);
end