multiple if conditions in matlab - matlab

while running the code below, the conditions (1) and (3) are not read in Matlab.
I tried my best but couldn't figure the mistake. Any help will be much appreciated.
% inputs are a_s, p, t, a
% a_s=single number
% p,t,a are column vectors
% output is P (also a column vector)
if a_s<a<=a_s-180
if p<=180-t %------(1)
P=p+t;
elseif p>180-t %------(2)
P=p+t-180;
end
elseif a<=a_s | a_s-180<a
if p>=t %------(3)
P=p-t;
elseif p<t %------(4)
P=p-t+180;
end
end

Try the following substitutions:
Substitute this:
if p<=180-t %------(1)
P=p+t;
elseif p>180-t %------(2)
P=p+t-180;
end
for this:
P = p+t;
P(P<=180) = P(P<=180)-180;
and this:
if p>=t %------(3)
P=p-t;
elseif p<t %------(4)
P=p-t+180;
end
for this:
P = p-t;
P(P<0) = P(P<0)+180;
as for the two ifs for a_s and a it's not clear if you want to execute the branch when any() condition is true or only if all of them are true (which is the default). Remember that a is a vector, so a<a_s is a boolean vector.

Related

How do I adjust this code so that I can enter how many runs I want and it will store each run in a matrix?

I have created this code to generate a 1 set of lottery numbers, but I am trying to make it so that the user can enter how many sets they want (input n), and it will print out as one long matrix of size nX6? I was messing around with a few options from online suggestions, but to no avail. I put the initial for i=1:1:n at the beginning, but I do not know how to store each run into a growing matrix. Right now it still generates just 1 set.
function lottery(n)
for i=1:1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
m=1;
lottonum1=floor(ylow+rand*(yhigh-ylow+1));
z = horzcat(lottonum, lottonum1);
end
disp('The lotto numbers picked are')
fprintf('%g ',z)
disp (' ')
The problem is that you are not storing or displaying the newly generated numbers, only the last set. To solve this, initialize z with NaNs or zeros, and later index z to store each set in a row of z, by using z(i,:) = lottonum.
However, you are using i as iterator in the while loop already, so you should use another variable, e.g. k.
You can also set z as an output of the function, so you can use this matrix in some other part of a program.
function z = lottery(n)
% init z
z = NaN(n,6);
for k = 1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
lottonum1 = floor(ylow+rand*(yhigh-ylow+1));
z(k,:) = horzcat(lottonum, lottonum1); % put the numbers in a row of z
end
disp('The lotto numbers picked are')
disp(z) % prettier display than fprintf in this case.
disp (' ')
end
The nice answer from rinkert corrected your basic mistakes (like trying to modify your loop iterator i from within the loop => does not work), and answered your question on how to store all your results.
This left you with a working code, however, I'd like to propose to you a different way to look at it.
The porposed architecture is to divide the tasks into separate functions:
One function draw_numbers which can draw N numbers randomly (and does only that)
One function draw_lottery which call the previous function as many times as it needs (your n), collect the results and display them.
draw_lottery
This architecture has the benefit to greatly simplify your main function. It can now be as simple as:
function Draws = draw_lottery(n)
% define your draw parameters
xmin = 1 ; % minimum number drawn
xmax = 69 ; % maximum number drawn
nballs = 5 ; % number of number to draw
% pre allocate results
Draws = zeros( n , nballs) ;
for iDraw=1:1:n
% draw "nballs" numbers
thisDraw = draw_numbers(xmin,xmax,nballs) ;
% add them to the result matrix
Draws(iDraw,:) = thisDraw ;
end
disp('The lotto numbers picked are:')
disp (Draws)
disp (' ')
end
draw_numbers
Instead of using a intricated set of if conditions and several iterators (i/m/k) to branch the program flow, I made the function recursive. It means the function may have to call itself a number of time until a condition is satisfied. In our case the condition is to have a set of nballs unique numbers.
The function:
(1) draws N integer numbers randomly, using randi.
(2) remove duplicate numbers (if any). Using unique.
(3) count how many unique numbers are left Nu
(4a) if Nu = N => exit function
(4b) if Nu < N => Call itself again, sending the existing Nu numbers and asking to draw an additional N-Nu numbers to add to the collection. Then back to step (2).
in code, it looks like that:
function draw = draw_numbers(xmin,xmax,nballs,drawn_set)
% check if we received a partial set
if nargin == 4
% if yes, adjust the number of balls to draw
n2draw = nballs - numel(drawn_set) ;
else
% if not, make a full draw
drawn_set = [] ;
n2draw = nballs ;
end
% draw "nballs" numbers between "xmin" and "xmax"
% and concatenate these new numbers with the partial set
d = [drawn_set , randi([xmin xmax],1,n2draw)] ;
% Remove duplicate
drawn_set = unique(d) ;
% check if we have some more balls to draw
if numel(drawn_set) < nballs
% draw some more balls
draw = draw_numbers(xmin,xmax,nballs,drawn_set) ;
else
% we're good to go, assign output and exit funtion
draw = drawn_set ;
end
end
You can have both functions into the same file if you want.
I encourage you to look at the documentation of a couple of Matlab built-in functions used:
randi
unique

how to set for-loop times limit and break the for-loop?

I would type the number 1~22. (because the number of figure is 22.)
( ex) when i type 1 then figure(1) is shown up. )
now i want to set times limit of this loop to 22.
because even i type all of them, they can't over 22.
and also i want to know the way end this loop without typing all number (less than 22).
i will show the code that i writed, please give me the advice.
for TNP=1:23
**% for-loop's end condition -->1. when i type all 22 number.
->2. when i type 23 to end the for-loop without typing more number.**
FN = input('Which figure do you want: ') **% here i would type the number of figure.**
if FN==1
F1=meshc(z(:,111:268))
grid on
hold on
elseif FN==2
F2=meshc(z(:,269:419))
grid on
hold on
elseif FN==3
F3=meshc(z(:,431:586))
grid on
hold on
.
.
.
else FN=23
close;
end
end
**% but even i add the 'break' for-loop doesn't end. what is the reason??**
You cannot use a loop here.
A loop is used when you want to repeat some code an specific number of times, which is not the case here (if I understood correctly).
What you want is to accept inputs from 1 to 22 to show the corresponding figures. I assume the figures don't have to be in order (otherwise you won't need a manual input)
You have to first define a number that will finish the loop (for example -1) and then use a while.
FN = input('Which figure do you want (1 to 22, or -1 to exit)?: ')
while FN ~= -1
if FN < 1 | FN > 22
disp (['Incorrect option: ' num2str(FN)]);
else
% your code to handle correct cases here
end
% now ask again
FN = input('Which figure do you want (1 to 22, or -1 to exit)?: ')
end
I agree with SembeiNorimaki -- your chosen design is a bit strange. I would go for something similar to what s/he wrote:
function myfcn()
% (define Z here)
% User input loop
while true
% Get the number
FN = input('Which figure do you want: ');
% Don't ever trust the user, even if
% the only user is you
if ~isnumeric(FN) || ...
~isscalar(FN) || ....
~isfinite(FN) || ...
~isreal(FN) || ...
FN > 23 || ...
FN < 0
warning([mfilename ':invalid_input'],...
'Invalid input; please insert a figure number 1-23, or 0 to exit.');
continue;
end
% It's always good to have an explicit exit condition
if FN == 0
break; end
% Apparently, you want this to be a special case
% (Note that this will only close the last figure drawn)
if FN == 23
close; end
% Call a handler to do all the heavy lifting
h = myGraphicsHandler(z, round(FN));
% ...Do whatever you want with this handle
end
end
function h = myGraphicsHandler(z, FN)
% These are the only things that seem to be
% different between each case
rangesTable = {111:268
269:419
431:586 % ... and so on
};
% create the figure
h = figure;
hold on
meshc(z(:, rangesTable{FN}));
grid on
% ... other operations / figure decorations here
end

Smarter way to index loops in Matlab

I have written a function (call it F) that works "well" (i.e. gives me the result I want) and inside it I call the exact same function (call it G_i) four times (below one of them) except each time I change the way I index my loop to be able to cover all pairs of coefficients in a matrix. I think this method is poor and I would like to know if you have ideas to improve it please...
I do this to check sequentially conditions on the coefficients of a matrix (sometimes in the order (1,2) then (1,3) then (2,3). I go on checking in different orders).
function G_1=countbackward(a,,,)
n=a;
G_1=[];
N=1;
while N>0
for l=n:-1:1
for m=1:l
if some condition on generated matrices
...
elseif another condition on generated matrices
...
else
N=0 ;
end
G_1=[G_1,g_0] ;
end
end
end
(for n=3 I get with the above the entries: (3,1),(3,2),(2,1).)
Other indexing I use with the exact same body of the above function :
for l=n:-1:1
for m=(l-1):-1:1
Same for the following:
for l=1:n
for m=l+1:n
Same for the following:
for l=1:n
for m=n:-1:l
Thank you for your help.
APPENDIX:
below is a simplified example of my code:
function H=count2backward(a,g_0,s,e)
%matrix g_0 is the "start" matrix
%matrix g_K is the "end" matrix
n=a; % number of nodes in an undirected graph or size A
s=mypayoff(n,g_0);
e=mypayoff(n,g_K);
H=[];
N=1;
while N>0
for l=1:n
for m=n:-1:l
if l~=m && g_0(l,m)==0 && s(l)<=e(l) && s(m)<=e(m) && (s(l)<e(l) || s(m)<e(m) ) ;
g_0(l,m)=g_0(l,m)+1 ;
g_0(m,l)=g_0(m,l)+1 ;
g_0 ;
s=mypayoff(n,g_0);
elseif l~=m && g_0(l,m)==1 && (s(l)<e(l) || s(m)<e(m) ) ;
g_0(l,m)=g_0(l,m)-1 ;
g_0(m,l)=g_0(m,l)-1 ;
g_0 ;
s=mypayoff(n,g_0);
else
N=0;
end
H=[H,g_0] ;
end
end
end
You can generate the indexes and pass them as a parameter. That lets you abstract deciding how to loop into another function.
indexes = countbackwardpattern(a);
G_1=g_i(a, indexes);

MATLAB force function to output n arguments

Is there a way in matlab to force a function to output a certain number of arguments? For example this is what matlab does:
function [a,b,c] = practice
if nargout >=1
a =1;
end
if nargout >=2
b=2;
end
if nargout ==3
c = 3;
end
end
d(1:3) = practice()
% d = [1 1 1]
I would want:
d(1:3) = practice()
% d = [1 2 3]
Can I get this behavior without needing to say
[d(1),d(2),d(3)] = practice()
There is an option to let your function output everything when only a single output argument is used:
function varargout=nargoutdemo(x)
varargout{1}=1;
varargout{2}=2;
varargout{3}=3;
if nargout==1
varargout={[varargout{:}]};
end
end
For non uniform return data, it might be necessary to switch to a cell
If you wish not to change the function, you could use this a little bit more generic code:
out=cell(1,3)
[out{:}]=practice
Please not, that this returns a cell, not an array. That's because array to comma separated list conversion is not directly possible.

Whats wrong with my function code (MATLAB/OCTAVE)

I am trying to make my program work. It is for prime numbers.
Below is my function then my main program
I believe this is the right formatting, (obviously I'm probably wrong cause its not working) and I have been trying to fix it to no avail. Any help will be most appreciated and an explanation of what I am doing wrong (I am pretty sure it has to do with subtle formatting) would be great too.
function [answer,primefactors ] = primey1 (N)
for i=2:(N-1)
A(i-1)=rem(N,i);
end
A;
if(all(A)==1)
answer=['Yes']
primefactors=[1,N]
elseif(all(A)==0)
answer=['No']
fac=[]
for i=2:N
q=0;
while N/i==floor(N/i)
N=N/i;
q=q+1;
end
if q>0
fac=[fac,i]
if N==1
break
primefactors=[fac]
end
end
end
end
endfunction
As noted by Magla, MATLAB comes with the primes and factor functions, which you can at least use to compare your implementation with and/or check your outcomes.
Anyway, as for your code, try this:
function [answer, primefactors] = primey1(N)
% Use vectorization for simple cases such as these:
A = rem(N,2:N-1);
if all(A)
answer = 'Yes';
primefactors = [1,N];
% Re-wrote this entire section. There were a bunch of things wrong with it:
% the order of commands was wrong, variables were not assigned for some N,
% etc. Just compare the two implementations
else
answer = 'No';
primefactors = [];
for ii = 2:N
q = 0;
while N/ii == floor(N/ii)
N = N/ii;
q = q+1;
end
if q > 0
primefactors = [primefactors,ii]; %#ok<AGROW>
if N==1
break;
end
end
end
end
end
Matlab has a factor function that does what your code is trying to do
p = factor(10)
returns 2, 5
and
p = factor(11)
returns 11.
All you have is to test for length
if length(p) == 1
is true for prime numbers.
The solution as offered by #Rody should do the job, in theory even more efficient than this, however to illustrate the concept of initialization, I would recommend you to initialize the output variables of your function right after the function start. In your case this would mean that I recommend starting the code like this:
function [answer, primefactors] = primey1(N)
% Function to determine whether a number is prime and which prime factors it has
% Assign default values
answer = 'No';
primefactors = [];