Creating logical arrays in matlab - matlab

I've been learning matlab for the past week as my job requires it, but I'm kinda stuck. I want to create a function that removes all data points within lowerBound and upperBound. What's wrong with this code?
mask = ~((data.HB_X > lowerBound) && (data.HB_X < upperBound));
data.HB_X = data.HB_X(mask);
data.HB_Y = data.HB_Y(mask);
The error is
??? Operands to the || and && operators must be convertible to logical scalar values.
Error in ==> myGUI>deleteHBs at 228
mask = ~((data.HB_X > lowerBound) && (data.HB_X < upperBound));

The problem is exactly what the error message says. You can only use the shortcut operators && and || for scalar comparisons. If you compare arrays, you need to use & and |, respectively.

Related

Why does this if statement give an output despite the && conditions not being satisfied?

I have been trying to execute a piece of code with some if conditions. This is a simple version of it.
X=100;Y=100;
if ((((X+1) && (Y+1))<=99) && (((X+1) && (Y+1))<=102))
disp(X);
end
Despite both X and Y not satisfying the first condition, I still get the output as 100. I have tried all combinations of & and && to make the and operations in the work. I checked the difference between the two and I found that & is a logical bit-wise operator while && is a short-circuit operator, which probably doesn't change much in this context. What's the error with this syntax?
Of course the code works when I do this:
X=100;Y=100;
if (X+1)<=99 && (Y+1)<=99 && (((X+1) && (Y+1))<=102)
disp(X);
end
But this is so inefficient when there are lot of conditions and each sub-condition must include the constraints. I'm sure this must be answered somewhere and this question might be a duplicate, so please point me to the answer.
So it looks like you understand what (X+1)<=99 && (Y+1)<=99 does. Let's look at ((X+1) && (Y+1))<=99:
&& requires a logical value on each side. a && b will turn a and b into logicals, effectively becoming a~=0 && b~=0. Thus:
((X+1) && (Y+1) ) <= 99
((X+1)~=0 && (Y+1)~=0) <= 99
( true && true ) <= 99
1 <= 99
true
Of course the truth value of (X+1)~=0 and (Y+1)~=0 could be different, but here you see this. In MATLAB, true is equal to 1 in a non-logical context, as when compared to 99.
If you want to simplify this expression, use max instead of &&:
X=100;Y=100;
if max(X+1,Y+1)<=99 && max(X+1,Y+1)<=102
disp(X);
end
If the max of a and b is smaller than 99, then both a and b are smaller than 99.
(Obviously, the statement can be further simplified to if max(X+1,Y+1)<=102, since if the second inequality holds than so must the first.)

Comparing Multiple File Types in an if Statement

I am importing a file into a function using [filepath, name, ext]=fileparts(thisFile);. I would then like to use a series of if statements that will operate on the file depending on its type; however, come files will have the same initial set up and so I would like to be able to include them all in an if statement. My current implementation: elseif (ext == '.s3p'). If I put in something like: elseif (ext == '.s2p' || '.s3p') the compiler whines,
Operands to the || and && operators must be convertible to logical scalar values.
You see my logic. Is there anything that I can do to make this work?
Thank you in advance!
You probably want strcmp, not ==. With a==b you get element-wise comparison. So you get a logical vector as result; and if a and b have different number of characters you get an error.
The fact that the output of == is a logical vector of element-wise comparisons is what causes the m-lint message. || and && require scalar arguments.
Lastly, in (ext == '.s2p' || '.s3p') you probably meant (ext == '.s2p' || ext == '.s3p').
Combining all of the above:
elseif strcmp(ext,'.s2p') || strcmp(ext,'.s3p')
For clarity and readability, you may prefer to use the ismember function with a cell array of the extensions to compare with:
elseif ismember(ext, {'.s2p' ,'.s3p'})
or, as pointed out by Cris Luengo,
elseif any(strcmp(ext, {'.s2p', '.s3p'}))
Better yet, instead of a series of elseif statements you may prefer to use switch, which implicitly applies strcmp / ismember for each case:
switch ext
case {'sp2', 'sp3'}
% Do stuff
case {'aaa', 'bbb'}
% Do stuff
otherwise
error('Unrecognized extension')
end

Checking for real positive integers

How can I improve (shorten) my check that values are real positive integer? I want to do it first for just an integer (a), for which I have tried
a~=floor(a) || a<=0 || imag(a)~=0
Secondly, I'd like to do it for a linked list
l=struct('xpos',value,'ypos',value,'entry',value,'next',[])
l=struct('xpos',value,'ypos',value,'entry',value,'next',l)
and so on.
For the list I want all xpos and ypos values to be real positive integers, I have tried
any(l.xpos~=floor(a) || l.xpos<=0 || imag(l.xpos)~=0 || l.ypos~=floor(l.ypos) || l.ypos<=0 || imag(l.ypos)~=0)
This ends up being quite long when I had two lists to check.
You could possibly simplify your check and turn it into an anonymous function using something like:
isPositiveInt = #(x)isscalar(x) && isnumeric(x) && abs(round(x)) == x && x > 0;
If it's guaranteed that it will always be a scalar and numeric you can simplify this to:
isPositiveInt = #(x)abs(round(x)) == x && x > 0;
Then you could easily perform this check for both xpos and ypos
isPositiveInt(S.xpos) && isPositiveInt(S.ypos)
To go through your "linked list" you'll just need to loop through it
while ~isempty(S)
% They they are both integers do something
if isPositiveInt(S.xpos) && isPositiveInt(S.ypos)
% Do something
end
% Go onto the next one
S = S.next;
end
As a side-note, it's best to avoid using a lower-case l as a variable since it looks a lot like the number 1. I have switched it out for S in the example above.

&& operators issue in MATLAB

Here is my code:
friendly_output = num2str(std(counts_channel),'%.4f');
if friendly_output > 0 && friendly_output <= 1000
variable = 100
elseif friendly_output > 1000 && friendly_output <= 1500
variable = 500
The variable friendly_output here is a decimal number. However, while I am executing this code, this prompts me the error:
Operands to the || and && operators must be convertible to logical
scalar values
I tried to solve the issue by replacing && with &, the program works, but the variable friendly_output failed to catch the correct if statement.
I tried to output the value of friendly_output, the value is correct but the statement it goes into is wrong.
Thank you.
If my guess is correct, your friendly_output is of type char
To check that, try this:
class(friendly_output)
If you need to compare it with an integer, you need to convert it back to a number.
To do this add this code after the first line
friendly_output = str2double(friendly_output);
%// changed from `eval` to `str2double` as suggested by #horchler
%// Using `str2double` over `eval` or `str2num` is a best practice.
%// or you could just avoid `num2str` conversion
PS:
The && operator didn't work for you because they work good only on scalar inputs. But as the friendly_output variable is a char array, you got the error.
While & works on array inputs, Each char is first converted to its corresponding ASCII value and then compared with the number. So even though Matlab doesn't post an error, the results won't be favorable to you.
For more information on the difference between & and && Refer Here
Here is an example of what is happening when you don't convert the string back to number:
>> a = '1200.5'
a =
1200.5
>> a > 1000
ans =
0 0 0 0 0 0
The ASCII values of char 0-9 ranges from 49-57 while ASCII value of char '.' is 46
Although, 1200.5 is greater than 1000, it actually calculate this way
50(char '1') is not greater than 1000.
51(char '2') is not greater than 1000.
49(char '0') is not greater than 1000.
49(char '0') is not greater than 1000.
46(char '.') is not greater than 1000.
54(char '5') is not greater than 1000.

Why does the && operator not appear to work in Matlab/Octave?

I'm playing around with some slightly modified Euler problems. The following code:
a=(0:1:999);
b=a(mod(a,5) == 0)
Appears to do the right thing. However with a slight modification:
a=(0:1:999);
b=a(mod(a,5) == 0 && mod(a,3) == 0)
I get
b=[](0x0)
What is happening here?
You want & instead of &&
The & operator performs an element-by-element AND between matrices, while the && operator performs a short-circuit AND between scalar values.