I want to write nested recursive function.
Example: Calculate sum of factorial of 1 to n numbers.
myfact(n) function calculate factorial of n.
function [ fact ] = myfact( x )
temp = 0;
if (x == 1)
temp = 1;
else
temp = x*myfact(x-1);
end
fact = temp;
end
myfactSum() function calculate the sum of return values of "myfact".
factNums is an array which contains each value's factorial. For example : factNums(2)=2!
function [total] = myfactSum(n,factNums)
if(n==1)
return
else
result = myfact(n);
factNums(n) = result;
total=sum(factNums);
myfactSum(n-1,factNums);
end
end
Testing it script above ;
n = 4;
factNums = zeros(1,n);
x=myfactnum(n,factNums);
y=0;
for i=1:checkValues
y=y+myfact(i);
end
At the results of script x=24, y=33
One recursive and loop find right answer, however nested recursive functions return only the factorial of last value.
I try to debug the recursive functions, it fill the factNums with values [1,2,6,24] end of the function values, but when it back to main script values dissapeared.
I change myfactSum, and it works :) It is so simple :)
function [sum] = myfactnum(n)
temp=1;
if(n==0)
temp=0;
else
temp=myfact(n)+myfactnum(n-1);
end
sum=temp;
end
Related
I am doing the following to generate random matrices with eigenvalues in a specific range:
function mat = randEig(dim, rReal)
D=diff(rReal).*rand(dim,1)+rReal(1);
P=rand(dim);
mat=P*diag(D)/P;
end
But I also want to be able to generate random real matrices with complex (conjugate) eigenvalues. How would one do that? The similarity transformation trick would return complex matrices.
EDIT: Okay I managed to do it by piggybacking on MATLAB's cdf2rdf function (which is basically the second function below).
function mat = randEig(dim, rangeEig, nComplex)
if 2*nComplex > dim
error('Cannot happen');
end
if nComplex
cMat=diff(rangeEig).*rand(dim-2*nComplex,1)+rangeEig(1);
for k=1:nComplex
rpart=(diff(rangeEig).*rand(1,1)+rangeEig(1))*ones(2,1);
ipart=(diff(rangeEig).*rand(1,1)+rangeEig(1))*i;
ipart=[ipart; -ipart];
cMat=[cMat; rpart+ipart];
end
else
cMat=diff(rangeEig).*rand(dim,1)+rangeEig(1);
end
D=cMat;
realDform = comp2rdf(diag(D));
P=rand(dim);
mat=P*realDform/P;
end
function dd = comp2rdf(d)
i = find(imag(diag(d))');
index = i(1:2:length(i));
if isempty(index)
dd=d;
else
if (max(index)==size(d,1)) | any(conj(d(index,index))~=d(index+1,index+1))
error(message('Complex conjugacy not satisfied'));
end
j = sqrt(-1);
t = eye(length(d));
twobytwo = [1 1;j -j];
for i=index
t(i:i+1,i:i+1) = twobytwo;
end
dd=t*d/t;
end
end
But the code is ugly, mainly the way rand is called multiple times is annoying). If someone wants to post an answer that calls rand once and manages to do the trick I will surely accept and upvote.
I made it either a single call or two calls with this:
function mat = randEig(dim, rangeEig, nComplex)
if 2*nComplex > dim
error('Cannot happen');
end
if nComplex
cMat=diff(rangeEig).*rand(2*nComplex,1)+rangeEig(1);
cPart=cMat(1:nComplex)*i;
cMat(1:nComplex)=[];
cPart=upsample(cPart,2);
cPart=cPart+circshift(-cPart,1);
cMat=upsample(cMat,2);
cMat=cMat+circshift(cMat,1);
cMat=cMat+cPart;
cMat=[diff(rangeEig).*rand(dim-2*nComplex,1)+rangeEig(1); cMat];
else
cMat=diff(rangeEig).*rand(dim,1)+rangeEig(1);
end
D=cMat;
realDform = comp2rdf(diag(D));
P=rand(dim);
mat=P*realDform/P;
end
function dd = comp2rdf(d)
i = find(imag(diag(d))');
index = i(1:2:length(i));
if isempty(index)
dd=d;
else
if (max(index)==size(d,1)) | any(conj(d(index,index))~=d(index+1,index+1))
error(message('Complex conjugacy not satisfied'));
end
j = sqrt(-1);
t = eye(length(d));
twobytwo = [1 1;j -j];
for i=index
t(i:i+1,i:i+1) = twobytwo;
end
dd=t*d/t;
end
end
If someone can make it a single call or shorter/more elegant code they are welcome to post an answer.
I made a simple function that loops between the rows and columns of an array using for loops. The loop is part of a function named checktakentest (Since I'm testing this method atm). I keep getting the error that there aren't enough input arguments.
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
if tttArray(h,j) == 1
%Is spot is taken, break loop
spotTaken = 1; break;
else
spotTaken = 0;
end
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
I tried also defining h and j previously as follows
h = [1,2,3];
j = [1,2,3];
Note that tttArray is a global variable defined in another function and its array values change in that function. A spot taken is 1, empty is 0. What arguments should I pass to the function and how do I know which ones to pass since this has been a recurring problem for me? A simple explanation would be appreciated. Note that I call the function via
checktakentest(tttArray)
Just remove the first if clause - at that point you don't have j initialized to a value, so you can't use it, yet:
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
If you call your function like this: checktakentest(tttArray) with tttArray beeing a mxn-matrix with m>2 and n>2 you should not get an error.
If you call it like this: checktakentest you will get the error you described (not enough input arguments).
I am new to matlab and I have couple of questions about it. First one, "Your function should terminate the sequence when either the value of ... or..." I use || in the code but it does not work as expected while && gives me the correct answer. Second question, how could the code be to display only the final answer?
Problem: calculate X which is represented by the sequence below
X = 1 - 1/2^2 + 1/3^2 - 1/4^2 +....
Requirement: Your function should terminate the sequence when either the value of 1/k^2 is less than 0.0001 or k is equal to k_max.
input k
Initialize x = 0
for loop i from 1 to k
if 1/i^2<0.0001 && i >= 100
break
end
Calculate X = (-1)^(i+1)./i^2 + X
end
You can use the break function as follows, where END_CONDITION is the condition you want to end your loop in.
if END_CONDITION
disp(X);
break;
end
To display the final answer, you can use the disp function. Eg. if your variable you want to print is called A then you use the following code.
disp(A)
Collectively this is your code. Since k_max terminates at the end of the for loop, we don't have to add any conditions to break out of the loop.
X = 0;
for i = 1:k
if 1/i^2<0.0001 || i==100
break;
end
X = (-1)^(i+1)./i^2 + X;
end
disp(X);
I have a problem at the beginning of my function. The function is to combine several data column from some objects. Error happens at the beginning of function. It says as follows:
Error in find_by_coor (line 2)
for i = 1:length(obj_ac)
Here is only the declaration of variable and loop, but Matlab somehow returned error. I have no idea so would like someone to help me. I attached my code as follows. Thanks a lot in advance.
function arr = find_by_coor(obj_ac,obj_gps,obj_sen_dir,lat1,long1,lat2,long2)
for i = 1:length(obj_ac)
if eq(obj_sen_dir(i).sensor,4) && strcmp(obj_sen_dir(i).direction,'outbound')
ind = obj_gps(i).save_var_gps(:,1)>lat1;
if isempty(find(ind)) == 1
continue
end
temp = obj_gps(i).save_var_gps(ind,:);
ind = temp(:,1)<lat2;
if isempty(find(ind)) == 1
continue
end
temp2 = temp(ind,:);
ind = temp2(:,2)<long1;
if isempty(find(ind)) == 1
continue
end
temp3 = temp2(ind,:);
ind = temp3(:,2)>long2;
if isempty(find(ind)) == 1
continue
end
temp4 = temp3(ind,:);
mint = min(temp4(:,5))-min(obj_gps(i).save_var_gps(:,5));
maxt = max(temp4(:,5))-min(obj_gps(i).save_var_gps(:,5));
if isempty(mint) == 1 || isempty(maxt) == 1
continue
end
if floor(mint*(1.6516e+03)) == 0 || floor(maxt*(1.6516e+03)) == 0
continue
end
temp5 = obj_ac(i).save_var(floor(mint*(1.6516e+03)):floor(maxt*(1.6516e+03)));
temp6 = abs(fft(temp5));
arr(i,:) = [i objs(i).daten var(temp5) max(temp5) min(temp5) mean(temp5) std(temp5) mode(temp5) var(temp6) max(temp6) min(temp6) mean(temp6) std(temp6) mode(temp6)];
disp(i);
end
end
end
The problem is that when you run the function, the output variable arr is never assigned. In Matlab you must always assign a function output if you choose to have it in the definition. For example
function [a,b] = setAB()
err = 0; % Gives an error if err is true
a = 1;
if ~err
b = 1;
end
The reason is most certainly that for some inputs, all values fall into one of the if statements and you do never reach the point where arr is assigned. A good solution for this is to assign a default value for arr in the beginning. That may for example be nan or -1 or, in your case maybe an array arr = nan(wanted size) or arr = -1*ones(wanted size). If you do not preallocate arr you will likely get a "matrix out of bounds" error instead, should you solve the first issue.
It does not mean that you always need to have an output though.
function [] = noOutput()
disp('Hi, I am a void!');
You may also choose to return as many values as number of outputs.
function varargout = variableArgs()
a = 1;
b = 2;
c = 3;
if (nargout == 1)
varargout{1} = a;
elseif (nargout == 2)
varargout{1} = b;
varargout{2} = c;
else
error('Wrong number of output arguments!');
end
I am not saying which of the approaches you should use or that any of them are good. Normally I use varargout in case I write plotting functions. Then I may want to return nothing in case I do not have an output argument. Then I want to return handles or any extra information. Further as you may have understood there is also a varargin that may be of more use.
I'm trying to code a function calculating difference quotients. I need to this for polynomial interpolation. Given nodes x = linspace(a,b,n+1), function values at the nodes y = func(x) I want to find the values of difference quotients f[x0], f[x_0,x_1], ..., f[x_0,x_1,...,x_n]. To calculate f[x_0,x_1,...,x_n] I will need f[x_0,x_1,...,x_(n-1)], etc., thus it would be a good idea save the intermediate steps on my way to f[x_0,x_1,...,x_n], so that on my way to f[x_0,x_1,...,x_n] I will save the preceding difference quotients as elements of a vector.
Could someone tell me how to correct my code in order to save appropriate difference quotient values? Here's the code:
function [fx, all_fx] = ilo2(a,b,x,y,fx,all_fx)
if a == b
fx(end+1) = y(a);
if a == 1
all_fx(end+1) = fx(end);
end
return
end
a;
b;
[c, all_fx] = ilo2(a+1,b,x,y,fx,all_fx);
[d, all_fx] = ilo2(a,b-1,x,y,fx,all_fx);
fx(end+1) = (c-d)/(b-a);
if a == 1
all_fx(end+1) = fx(end);
end
end
The difference quotients I need are under 'if a == 1' condition.
Ok, I think I fixed it:
function [all_fx,fx] = ilo(a,b,x,y,all_fx,fx)
if a == b
fx(end+1) = y(a);
if a == 1
all_fx(end+1) = fx(end);
end
return
end
[all_fx,c] = ilo(a+1,b,x,y,all_fx,fx);
[all_fx,d] = ilo(a,b-1,x,y,all_fx,fx);
fx(end+1) = (c-d)/(b-a);
if a == 1
all_fx(end+1) = fx(end);
end
end