I am writing an easy IF condition. The function is to judge each row of the matrix to be certain vectors. The code is as follows:
if (compareM(i,:)==[1, 0])||(compareM(i,:) ==[2, 1])
match_1 = match_1 +1;
else
mismatch_1 = mismatch_1 +1;
end
The error said ''Operands to the || and && operators must be convertible to logical scalar values''.
compareM is a n by 2 matrix and I wonder if the error is made by || operation. Thanks in advance!
If you are comparing vectors, not scalar values, you have to use | operator. As a result you get logical vector of element-by-element pairwise comparison. To use it in IF statement you have to convert either each logical statement (then use ||) or the result of | the to scalar with ALL, ANY or other function.
If you want to compare to vectors for equality use ISEQUAL function as
if isequal(compareM(i,:)==[1, 0]) || isequal(compareM(i,:)==[2, 1])
compareM(i, :) evaluates to a 1x2 numeric array, so compareM(i,:)==[1, 0] evaluates to a 1x2 logical array. The same for the expression to the right of the || sign. But you need a single logical value on each side of ||, not a 1x2 array of logical values.
If you want this expression to evaluate to true if both values on the lhs of == are the same as the corresponding elements on the rhs, wrap all() around each side:
all(compareM(i,:)==[1, 0]) || all(compareM(i,:) ==[2, 1])
if ((compareM(i,:)==[1, 0])||(compareM(i,:) ==[2, 1]))
match_1 = match_1 +1;
else
mismatch_1 = mismatch_1 +1;
end
Note the outer enclosing parentheses.
Related
I just found the statement any('') returns a logical 0, while the statement all('') returns a logical 1.
If the function any does not think the empty string ('') as nonzero, the function all should do the same, but from the result, the function all seems to think the empty string ('') as nonzero.
BTW, the similar thing happens where any(NaN) returns logical 0 while all(NaN) returns logical 1.
Is it a MATLAB bug?
Here is the version information of the MATLAB I am using.
MATLAB Version: 9.1.0.441655 (R2016b)
MATLAB License Number: DEMO
According to the Documentation
definition of any:
any(x) ...determines if any element is a nonzero number or logical 1 (true)
In practice, any is a natural extension of the logical OR operator.
If A is an empty 0-by-0 matrix, any(A) returns logical 0 (false).
and definition of all:
all(x) ...determines if the elements are all nonzero or logical 1 (true)
In practice, all is a natural extension of the logical AND operator.
If A is an empty 0-by-0 matrix, then all(A) returns logical 1 (true).
We can implement both functions:
function out = Any(V)
out = false;
for k = 1:numel(V)
out = out || (~isnan(V(k)) && V(k) ~= 0);
end
end
function out = All(V)
out = true;
for k = 1:numel(V)
out = out && (V(k) ~= 0);
end
end
Explanation:
-In any we assume that all elements are not nonzero [so all are zeros] and we want to prove that the assumption is wrong so we provide an initial value of false.
-Because any is a natural extension of the logical OR operator we use ||
-Because we should check for nonzero numbers we use V(k) ~= 0
-Because we should check for nonzeros numbers and NaN is Not a Number we use ~isnan(V(k)).
-In all we assume that all elements are nonzero [so all are ones] and we want to prove that the assumption is wrong so we provide an initial value of true
-Because all is a natural extension of the logical AND operator we use &&
-Because we should check for nonzeros we use V(k) ~= 0
-Because the definition of all doesn't force that nonzero elements to be numbers we don't use ~isnan(V(k))
Any returns 0 because it is not the case that any of its elements are true. An any clause is true if any of its elements are true.
All returns 1 because it is the case that all of its elements are true. All of its elements are true so long as none of its elements are false, and none of its elements are false.
It is convenient and consistent w.r.t the rest of your math when applying an associative operation over an empty list of values returns the neutral element of that operation. This is why
a sum of zero numbers is 0
a product of zero numbers is 1
a logical or of zero booleans is false
a logical and of zero booleans is true
Keywords for further reading: monoid, fold.
I just found solid proof from the documentation about the any and all functions, as follows.
Documentation of the function any
https://www.mathworks.com/help/matlab/ref/any.html
If A is an empty 0-by-0 matrix, any(A) returns logical 0 (false).
Documentation of the function all
https://www.mathworks.com/help/matlab/ref/all.html
If A is an empty 0-by-0 matrix, then all(A) returns logical 1 (true).
And the empty string in MATLAB is actually a 0×0 empty char array (I just found it). That explains my original question, from the documentation.
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.
My goal is to compare two matrices: A and B in two different files:
function [Result]=test()
A_Mat= load('fileA', 'A')
B_Mat= load('fileB', 'B')
Result= A_Mat == B_Mat
end
The result that I want is a matrix that includes the difference between A and B.
The error that I have is:
error: binary operator '==' not implemented for 'scalar struct' by 'scalar struct' operations
The load function doesn't return what you think it returns. Reading the extensive and easily comprehensible MATLAB documentation always helps.
function Result=test()
load('fileA', 'A');
load('fileB', 'B');
Result = A == B
end
Use the isequal function.
isequal(A,B)
If you simply want the difference between A and B you should first use load as dasdingonesin suggested, and either check for full matrix equality with isequal or elementwise equality with ==. The difference, however, is simply given by - of course:
isequal(A,B); % returns a boolean for full matrix equality
A==B; % returns a logical matrix with element wise equality
A-B; % returns a matrix with differences between the two matrices
Do note that isequal can deal with matrices of unequal size (it will simply return 0), whilst both == and - will crash with the error Matrix dimensions must agree.
First, the operator == does work on matrices, and it returns a logical matrix of true/false (1/0) where the corresponding items are equal or different respectively. From the error you got it seems that you didn't read matrices from the file, but structs, and indeed, == doesn't work for structs.
You can use isequal for both structs and matrices. This function returns only one value - 1 or 0 (true/false).
ADDED
After seeing #dasdingonesin answer, who actually pointed to the exact problem, I just wanted to add that when you write
A_Mat= load('fileA', 'A')
it returns a struct as with the field A.
So:
A_Mat = s.A
I have a data.txt file like:
123 124 125 126
I want to compare these number against num
My code is like this
data= textread('data.txt','%d');
num = 125;
if num == data
b = 1;
else
b = 0;
end
but answer shows 0 ( b = 0 )
how to scan these numbers?
Here is a quote from the doc page of eq function (the functional form of == operator):
A == B
If one input is scalar and the other a nonscalar array, then the
scalar input is treated as if it were an array having the same
dimensions as the nonscalar input array. In other words, if input A is
the number 100, and B is a 3-by-5 matrix, then A is treated as if it
were a 3-by-5 matrix of elements, each set to 100. MATLAB returns an
array of the same dimensions as the nonscalar input array.
And here is the relevant section from the docs of if statement:
if expression
statements
end
An evaluated expression is true when the result is nonempty and
contains all nonzero elements (logical or real numeric). Otherwise,
the expression is false.
So perhaps you meant to use:
if any(data == num)
disp('number found')
end
I have a mesh grid defined as
[X, Y, Z] = meshgrid(-100:100, -100:100, 25); % z will have more values later
and two shapes (ovals, in this case):
x_offset_1 = 40;
x_offset_2 = -x_offset_1;
o1 = ((X-x_offset_1).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
o2 = ((X-x_offset_2).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
Now, I want to find all points that are nonzero in either oval. I tried
union = o1+o2;
but since I simply add them, the overlapping region will have a value of 2 instead of the desired 1.
How can I set all nonzero entries in the matrix to 1, regardless of their previous value?
(I tried normalized_union = union./union;, but then I end up with NaN in all 0 elements because I'm dividing by zero...)
Simplest solution: A=A~=0;, where A is your matrix.
This just performs a logical operation that checks if each element is zero. So it returns 1 if the element is non-zero and 0 if it is zero.
First suggestion: don't use union as a variable name, since that will shadow the built-in function union. I'd suggest using the variable name inEitherOval instead since it's more descriptive...
Now, one option you have is to do something like what abcd suggests in which you add your matrices o1 and o2 and use the relational not equal to operator:
inEitherOval = (o1+o2) ~= 0;
A couple of other possibilities in the same vein use the logical not operator or the function logical:
inEitherOval = ~~(o1+o2); % Double negation
inEitherOval = logical(o1+o2); % Convert to logical type
However, the most succinct solution is to apply the logical or operator directly to o1 and o2:
inEitherOval = o1|o2;
Which will result in a value of 1 where either matrix is non-zero and zero otherwise.
There is another simple solution, A=logical(A)