How to recursively reduce the function arguments

조회 수: 4 (최근 30일)
Victoria Li
Victoria Li 2021년 11월 9일
댓글: Victoria Li 2021년 11월 10일
Is there a way to create a function with one less argument dynamically? Basicly I'd like to find a way to do the following recursively or in a loop.
f4 = @(x1,x2,x3,x4) f5(x1, x2, x3, x4, 1);
f3 = @(x1,x2,x3) f4(x1, x2, x3, 1);
...
f1 = @(x1) f2(x1, 1);
r = f1(1)
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5
end
  댓글 수: 2
David Hill
David Hill 2021년 11월 9일
Very confusing. An example would be helpful. It seems to me that r=f1=f2=f3=f4=f5=4+x1; which equals 5 in the example above (x1=1). Not sure what you are trying to do, but it is not wise to have all those variables.
Victoria Li
Victoria Li 2021년 11월 9일
Here is an example to calculate the double integral from 0 to 1 with composite simpson's rule. The function simpson2 takes a function argument. In the simpson2 function, I can only start the calculation when the function is a single variable. In the code below, I can transform the 2 variable function to a single variable function with given y values. I am looking for a more generic way to do this so it can handle integrals with more variables. To do this, it requires to transform the integral function with one less variable until it has only a single variable in each recursive iteration. The question above is simplified for achieving this.
f = @(x,y) (x.^2 + y.^2 );
a = 0;
b = 1;
m = 100;
integral = simpson2(a, b, m, f)
exact = integral2(f,a,b,a,b)
fprintf("Numerical Integral = %5.3f, Exact = %5.3f\n", integral, exact);
function integral = simpson2(a, b, m, fun)
% a, b: intregral boundary
% m: number of panels
% fun: function for integral
h = (b - a)/(2*m);
xi = a:h:b;
if nargin(fun) == 2
for i=1:length(xi)
fx = @(x) fun(x, xi(i)); % tranform to a single variable function with giver y varle
fx_val(i) = simpson2(a , b, m, fx);
end
elseif nargin(fun) == 1
fx_val = fun(xi);
fx_val(1);
else
fprintf("ERROR")
end
odd = double(sum(fx_val(3:2:end-1)));
even = double(sum(fx_val(2:2:end-1)));
integral = double(h/3 * (fx_val(1) + fx_val(end) + 4*(odd) + 2*(even)));
end

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2021년 11월 9일
It can be done with VARARGIN:
N = 5;
C = cell(1,N);
C{N} = @f5;
for k = N-1:-1:1
C{k} = @(varargin) C{k+1}(varargin{:},1);
end
C{1}(1)
ans = 5
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5;
end
  댓글 수: 1
Victoria Li
Victoria Li 2021년 11월 10일
Thanks Stephen for the help. Your solution works perfectly.

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Jan
Jan 2021년 11월 9일
This should work with str2func and eval.
This is such a cruel programming technique, that I recommend not to use it. Such meta-programming for creating code dynamically is hard to debug and Matlab's JIT acceleration cannot work. This can slow down the code by a factor 100 compared to some code, which avoid the dynamic creation of variables and functions.
  댓글 수: 1
Adam Danz
Adam Danz 2021년 11월 9일
The function string could also be parsed to remove the penultimate input and then converted back to a function handle without using eval. But I still think there's a better approach.

댓글을 달려면 로그인하십시오.


Adam Danz
Adam Danz 2021년 11월 9일
x1 = rand(1);
x2 = rand(1);
x3 = rand(1);
x4 = rand(1);
p = [x1, x2, x3, x4];
f5([p,1])
ans = 3.3148
p = [x1, x2, x3];
f5([p,1])
ans = 2.4283
p = [x1, x2];
f5([p,1])
ans = 1.8867
function f5(varargin)
sum([varargin{:}])
end

카테고리

Help CenterFile Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by