how to compare matlab cells or structs [duplicate] - matlab

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
>>

Related

Why are multiple, consecutive plusses allowable syntax in MATLAB?

Does anyone know why this works in MATLAB?
>> 1 ++ 2
ans =
3
Coming from coding in C, python, Java etc, I find it most counterintuitive that this should work at all. Presumably there's something important about the parser that I don't understand?
There's a difference between plus and uplus. I suspect MATLAB takes the first + as plus, and all the others as uplus. Since uplus is by default just "return what's behind", you add 1 and 2, and use a lot of "return what's behind" in between.
a=2;
c=+a % unitary plus
c =
2
1+2 % addition
ans =
3
1+++2 % addition and two uplusses
ans =
3
The reason uplus exists is to allow operator overloading in classes. The same works in other languages, e.g. in C#, to allow for operator overloading in confined classes.
The other reason mentioned in that C# thread is that is changes unsigned shorts to integers, which is not the case for MATLAB:
d=uint8(1)
d =
uint8
1
+d
ans =
uint8
1
a=+d
a =
uint8
1
It does, however, convert a boolean to a double, thanks to Cris Lunego for pointing that out:
+true
ans =
1
+false
ans =
0
The following however remains a mystery to me, inspired by Sanjay Manohar's comment:
>> [1 ++ 2]
ans =
1 2 % Two unary plusses
>> [1 + + 2]
ans =
3 % A normal plus and a unary one
>> [1++2]
ans =
3 % A normal plus and a unary one
The same works with multiple plusses, [1 +++..+++ 2], so with all plusses consecutively in the middle generates [1 2], all other combinations (as far as I tested) result in 3. I asked a separate question about this: Why do the plus and unary plus behave strange in array syntax?

If statement comparions: Matrix and number [closed]

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.

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: Vectorize the transpose in one step? [duplicate]

This question already has an answer here:
effective way of transformation from 2D to 1D vector
(1 answer)
Closed 9 years ago.
I would like to use the (:) operator and the transpose at the same time. Is this possible? Basically I would like to do something like
output = A'(:)
except that this does not work. Does anyone know a workaround?
Thanks!
Immo
The : operator in this case is shorthand for reshaping the matrix into a vector. You can work around the limitation of where you use the operator by using the reshape function explicitly:
octave> A = [1 2;3 4]
A =
1 2
3 4
octave> B=A'
B =
1 3
2 4
octave> C=B(:)
C =
1
2
3
4
octave> D=reshape(A',[],1) #% vectorize transpose in one line
D =
1
2
3
4
Try with:
output = reshape( A.', numel(A), 1);
>> A = rand(4,3);
>> output = reshape( A.', numel(A), 1);
A =
0.447213 0.046896 0.679087
0.903294 0.768745 0.651481
0.701071 0.122534 0.611390
0.535844 0.478595 0.772810
output =
0.447213
0.046896
0.679087
0.903294
0.768745
0.651481
0.701071
0.122534
0.611390
0.535844
0.478595
0.772810
Beware that reshape reads the matrices accessing along columns so you may not need to transpose the matrix A.
Also, remember that the operator ' is the hermitian operator, namely, conjugated of the transposed, whereas .' is simply transposition, which you could also get by transpose(A).
You may want to do everything in a single line without re-typing all every time. One solution is creating a function handles as boop:
>> boop = #(x) reshape( transpose(x), numel(x), 1)
>> output = boop(A)
output =
0.447213
0.046896
0.679087
0.903294
0.768745
0.651481
0.701071
0.122534
0.611390
0.535844
0.478595
0.772810