If statement comparions: Matrix and number [closed] - matlab

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a matrix A = [0 4 5 3] and the the number B=4.
No I want to do the following.
if A<B
disp('Something')
end
But this doesn't work, Matlab wont compare a matrix to a number. How can I solve this.

Matlab will compare a matrix (or, more properly, an array) to a number, the result of that operation will just be another array (of type logical). Boolean tests in if- and for-statements require a single logical to operate on. You need to convert your logical array to a single value by using any() (will return true if any of the elements is true) or all() (will return true if all of the elements are true).
For example:
if any(A<B)
disp('Something');
end
For more insight into what's going on:
>> A = [0 4 5 3]; B = 4;
>> A < B
ans =
1 0 0 1
>> any(A<B)
ans =
1
>> all(A<B)
ans =
0

An addition to the answer by #EelkeSpaak,
If you want to repeat an action each time that the statement is valid, you might need the following script:
for ii=find(A<B)
disp(num2str(A(ii)));
end
It depends on what you want to achieve.

The result of comparision of A = [0 4 5 3] and B=4 will be a logical matrix:
>> A = [0 4 5 3]
A =
0 4 5 3
>> B=4
B =
4
>> A<B
ans =
1 0 0 1
>> class(A<B)
ans =
logical
When you use a matrix in if statement it will be considered true if it is non-empty and all elements are non-zero
>> if A<B, disp('somthing'); end
>> B = 10
B =
10
>> if A<B, disp('somthing'); end
somthing
So it depends what is your expected behaviour of this comparison. You can use other function like all, any or isequal.

Related

Exporting matrix with Logical indexing in Matlab

I trying to export logical 1 indices of a matrix to another variable without altering their position. Below I am trying to explain my doubt using a example:
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
B = zeros(size(A));
B = A(l)
produces:
B =
1
5
6
3
7
4
But what I am interested in getting is
B =
1 0 3 4
5 6 7 0
Can anyone help me? Thanks
While you could use #tim's approach for this specific example, a more general solution is to use the logical array to index both the thing you're retrieving values from and the array you're assigning into. This grabs the values in A at the TRUE locations in I and places them into the corresponding positions in B.
I = logical([1 0 1 1; 1 1 1 0]);
A = [1 2 3 4; 5 6 7 8];
B = zeros(size(A));
B(I) = A(I);
The element-wise multiplication approach won't work if you want the "default" values in B to be anything other than 0. For example.
% Initialize B to an array of 100's
B = 100 * ones(size(A));
% Replace the elements specified by the logical array
B(I) = A(I);
% 1 100 3 4
% 5 6 7 100
Alternately, if you just want to zero-out the values in A you can also use logical indexing to do this.
A(~I) = 0;
As a sidenote, try to avoid using l for a variable name as it is very difficult to distinguish l from the number 1.
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
A .* l % element-wise multiplication
no prob, you are welcome ;-) Accept, question closed! xD
EDIT
I'm afraid Stackoverflow became a page where everyone tries to beat other's answers by trying to make a longer and more detailed answer, even though not related to WHAT WAS ORIGINALLY ASKED. And not the one's which give a quick, easy, simple solution within a small amount of time, to exactly that SPECIFIC QUESTION. Suever immediately becomes an upvote by answering a question which was NOT asked, just because it is longer.
I'll also play the game and edit my answer: If you want to have other default options then 0, one could also adopt my solution and use:
~l*default_value + A.*l
I just want to say: It IS possible.
EDIT2
tic;
for i = 1:1000000
B = A.*l;
end;
toc
>> Elapsed time is 2.18214 seconds.
tic;
for i = 1:1000000
B=zeros(size(A));
B(l)=A(l);
end;
toc
>>Elapsed time is 13.9691 seconds.
Choose for yourself.
EDIT3 (Default value != 0)
>> tic; for i = 1:1e6; B = A.*l+100*(~l); end; toc
Elapsed time is 4.17261 seconds.
>> tic; for i = 1:1e6; B=100*ones(size(A)); B(l)=A(l); end; toc
Elapsed time is 14.2126 seconds.

Matlab: Fast implementation of the assignment operator (subsasgn) multi-leveled object/array objects. [duplicate]

This question already has answers here:
setting object properties value for object array in matlab
(3 answers)
Closed 8 years ago.
So I have a class called agent with these following properties:
classdef agent < handle
properties
x
v
goal
v_pref
end
Here, x and v are 1-by-2 vectors. Let's suppose that I have an n-by-1 object array where each part of the array contains instances of the class called agent. Currently, I am having trouble overwriting the assignment behavior of my code. Whenever I am doing something like this:
obj.x([1;3], 1) = [ 5; 3];
I want to overwrite object 1 and 3s 1st element of x with 5 and 3, respectively.
So essentially I want these commands to be equivalent as above
obj(1).x(1) = 5;
obj(3).x(1) = 3;
Is there a way to do this in matlab using subsasgn or any other overloading function.
The problem with subsasgn and subsref:
>> obj([1,3])
ans =
1x2 agent array with properties:
x
v
goal
v_pref
>> obj([1,3]).x
ans =
0 5
ans =
0 3
>> obj([1,3]).x(2)
Scalar index required for this type of multi-level indexing.
>>
It seems Matlab isn't designed to handle this intention.
Also, with the following code:
S(1).type='()';
S(1).subs={1,3};
S(2).type='.';
S(2).subs='x';
S(3).type='()';
S(3).subs={2};
subsref(obj,S)
According to Mathworks' documentation, S(1).subs={1,3}; means to access obj(1,3), but not obj([1,3]). Changing it to S(1).subs={[1,3]}; also leads to the previous error.
Here's an alternative way.
Add this method to the class:
methods
function storex(obj,ind,x)
if length(x) == 1
x = repmat(x,length(ind),1);
end
for ii = 1:length(ind)
obj(ind(ii)).x(2) = x(ii);
end
end
end
and call it as
>> obj.storex([1,3],8)
>> obj.x
ans =
0 8
ans =
[]
ans =
0 8
>> obj.storex([2,3],[4,3])
>> obj.x
ans =
0 8
ans =
0 4
ans =
0 3
>>
Possible reference: "The expression a(:) does not produce a single output object, but rather a stream of them. MATLAB just hasn't been designed to apply two levels of indexing to a stream of them. It can do this a(:).b, but apparently not this a(:).b.c"
https://www.mathworks.com/matlabcentral/newsreader/view_thread/245627

Remove values from a vector based on restriction

If i have a vector (array) in matlab, is it possible to remove the values from that vector based on some restriction (e.g.. all non negative numbers).
Can you please advise me on the best approach to do that.
Yes, you can either use logical indexing to keep the values which meet a criterion or use the find function to get the indexes which hold values that meet a criterion.
logical indexing
the find function
An example of logical indexing where we want to remove all the values from a vector which are not greater than three:
>> x=[1,2,3,4,5,6]
x =
1 2 3 4 5 6
>> x=x(x>3)
x =
4 5 6
You can also ask for multiple criteria as you would expect. In the following example, we want to keep every value which is greater than three, but not five.
>> x=[1,2,3,4,5,6]
x =
1 2 3 4 5 6
>> x=x(x>3 & x~=5)
x =
4 6
Finally, the find function can come in handy when you need the indexes of values which meet a criterion.
>> x=[1,1,2,2,5,5]
x =
1 1 2 2 5 5
>> ind=find(x>3)
ind =
5 6
Logical indexing and find can also be applied to matrices with more than one row/column.
Thanks #Alan for helping me improve the answer.
You may want to look into logical indexing, as it neatly handles your problem.
To use the example you gave, if you have a vector a of numbers, and you want to remove all negative numbers you could do the following:
b = a(a >= 0);
which would create a vector b containing only the positive elements of a, or you could try:
a(a < 0) = [];
would set any elements in the vector a to []

matlab. vectorization within if/else if/else statements

I need some help with the following code:
if x(:,3)>x(:,4)
output=[x(:,1)-x(:,2)];
elseif x(:,3)<x(:,4)
output=[x(:,2)-x(:,1)];
else
output=NaN
end
Here is a sample data:
matrix x output
10 5 1 2 -5
10 5 2 1 5
NaN 1 1 3 NaN
I'm not sure how to make the code work. It just takes the first argument and ignores the else if and else arguments. Please help. Thank you.
if x(:,3)>x(:,4) doesn't really work, if expects either true or false not a vector. So it only evaluates the first element of the vector x(:,3)>x(:,4) which is why it appears to ignore your elseif.
So you must either use a loop or even better you can use logical indexing like this:
x= [10 5 1 2
10 5 2 1
NaN 1 1 3]
output = NaN(size(x,1),1)
I = x(:,3)>x(:,4);
output(I) = x(I,1)-x(I,2);
I = x(:,3)<x(:,4);
output(I) = x(I,2)-x(I,1)
Using sign to avoid indexing for different conditions.
B=diff(x,1,2);
B(B(:,3)==0,3) = NaN;
output = B(:,1) .* sign(B(:,3));
Or in a shorter and less readable form:
B=diff(x,1,2);
output = B(:,1) .* (sign(B(:,3))+0./sign(B(:,3)));
Here is how you can do it:
output = NaN(size(x,1),1);
idx1 = x(:,3)>x(:,4);
idx2 = x(:,3)<x(:,4);
output(idx1) = x(idx1,1)-x(idx1,2);
output(idx2) = x(idx2,2)-x(idx2,1);

how to compare matlab cells or structs [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Octave/MATLAB: How to compare structs for equality?
is there a simple comparison function for matlab cell or struct objects?
using '==' doesn't seem to work :(
If you want to know if two cell arrays or struct objects are exactly equal you could always use isequaln.
Use isequal to compare two cells. Note however that == is not advised even for arrays:
>> A = [1 2 3 4 5];
>> B = [1 2 3 4 5];
>> A == B
ans =
1 1 1 1 1
You would need to use a further trick to use that expression in a if statement for instance.
The reason == is not recommended for variables of type double is because of the IEEE 754 representation use by MATLAB. For instance:
>> .1 + .1 + .1 == .3
ans =
0
To compare double values more robustly, you can use the abs function in MATLAB:
>> if ( abs( (.1+.1+.1) - .3 ) < 1e-10 ); disp('Values are pretty close although not necessarily bit equal'); end
Values are pretty close although not necessarily bit equal
>>