Checking for real positive integers - matlab

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.

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

How do I operate on sevaral arrays in one loop MATLAB

I think it's a simple one
I have 8 arrays T03 and I want to check for some conditions in every one of them in a single loop. Here's what I'm talking about:
while(i<length(RRs)+1)
if T03_i(2,4)>0 && RRs(1:2,i)<0
RRs(1:2,i) = 0;
end
i=i+1;
end
As you see, I want to change elements in RRs array based on conditions in both RRs and T03_1/T03_2/T03_3/.../T03_8. Since T03_i doesn't work, do you have any suggestions?
Seems like the T03_i arrays are of the same size. You can combine them in one 3D array like this:
T3D = cat(3,T03_1,T03_2,T03_3,T03_4,T03_5,T03_6,T03_7,T03_8)
Then
V_mn = squeeze(T3D(m,n,:));
will give you a vector of elements from m-th row and n-th column from all the T03_i arrays at once and you can loop through them like V_mn(i) (here i has the same meaning as in your T03_i).
I suppose that you need all of the T03 arrays to be checked:
while(i<length(RRs)+1)
if T03_1(2,4)>0 ...
&& T03_2(2,4)>0 ...
&& T03_3(2,4)>0 ...
&& T03_4(2,4)>0 ...
&& T03_5(2,4)>0 ...
&& T03_6(2,4)>0 ...
&& T03_7(2,4)>0 ...
&& T03_8(2,4)>0 ...
&& RRs(1:2,i)<0
RRs(1:2,i) = 0;
end
i=i+1;
end

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.

Creating logical arrays in 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.