Matlab 为迭代函数组合定义泛型函数
让我们定义任何函数句柄Matlab 为迭代函数组合定义泛型函数,matlab,function,handle,Matlab,Function,Handle,让我们定义任何函数句柄foo: foo = @(x) x*2 我正在尝试编写一个通用函数defFun,该函数生成函数foo,即n次迭代调用foo,以一种可以存储在另一个句柄函数boo中的方式,如下所示: boo = defFun(foo,n) >> boo = defFun2(foo,3) boo = @(x)cfoo{1}(cfoo{1}(cfoo{1}(x))) // <= your function does not show what it does (o
foo
:
foo = @(x) x*2
我正在尝试编写一个通用函数defFun
,该函数生成函数foo
,即n次迭代调用foo
,以一种可以存储在另一个句柄函数boo
中的方式,如下所示:
boo = defFun(foo,n)
>> boo = defFun2(foo,3)
boo =
@(x)cfoo{1}(cfoo{1}(cfoo{1}(x))) // <= your function does not show what it does (only the number of time it calls itself)
比如说,
foo = @(x) x^2;
boo = defFun(foo,3);
boo(3)
将给出6561[==foo(foo(foo(3))]]
和boo(2)
将给出256[==foo(foo(2))]]
我试图用这段代码编写defFun
,但这些句柄很难处理。有什么想法吗
function boo = defFun(foo,n)
h = foo;
for i=2:n
h = h(h);
end
boo = h
end
你只是把你的变量搞混了。您的问题是将函数句柄馈送给匿名函数,而不是值 这将在您的示例的基础上起作用
foo = @(x) x^2;
function boo = defFun(fcn_handle,n)
v = fcn_handle(n); % The output here is the value of the anonymous function
for i=2:n
v = fcn_handle(v);
end
boo = v;
end
defFun(foo,3)
ans = 6561
如果函数句柄
foo
仅包含数学公式(如示例中所示),则可以使用MATLAB符号工具箱计算boo
function boo = defFun(foo,n)
syms x; % Create a symbolic variable x
f = sym(foo); % Convert the function handle to a symbolic expression
g = symfun(f,x); % Create a symbolic function to work with
v = g;
for k=2:n % repeat n times
v = g(v);
end
boo = matlabFunction(v); % convert v to a function handle
end
在n=3
的示例中,这将创建函数句柄
foo = @(x) x.^2;
boo = defFun(foo,3)
boo =
@(x)x.^8
boo(3)
ans =
6561
这里的3种解决方案依赖于构建一个字符串,然后使用
str2func
从中获取函数句柄。相同功能的不同实现,但结果的可读性不同
请注意,正如注释中强调的(感谢knedlsepp),递归的顺序n
不能超过32
一种方法是解析输入函数字符串定义,并在将其转换为函数句柄之前在字符串中递归地重新创建它:
function boo = defFun(foo,n)
%% // retrieve the string of the initial function
A = functions(foo) ;
fstrfull = A.function ;
%% // find "input variables" in the header
[i1 i2] = regexp(fstrfull, '\(([^\)]+)\)' , 'once' ) ; %// probably can be improved, regexp are not my strong suit
strVar = fstrfull(i1+1:i2-1) ; %// => strVar='x' %// to get rid of the parenthesis returned by the regex
%% // isolate only the function expression (without the header)
ilast = strfind( fstrfull , ')' )+1 ; %// ilast= 5 find the last position of the header
fstr = fstrfull(ilast(1):end) ; %// fstr='x.^2' separate only function expression
%% // replace "variables" by the expression the desired number of time
strFinalFunction = fstr ;
for i=2:n
strFinalFunction = strrep(strFinalFunction, strVar, ['(' fstr ')'] ) ;
end
boo = str2func( ['@(' strVar ')' strFinalFunction ] ) ;
end
这将为您提供:
>> boo = defFun(foo,3)
boo =
@(x)((x.^2).^2).^2 // <= your function shows the full expression
>> boo(3)
ans =
6561
但现在您的函数定义如下所示:
boo = defFun(foo,n)
>> boo = defFun2(foo,3)
boo =
@(x)cfoo{1}(cfoo{1}(cfoo{1}(x))) // <= your function does not show what it does (only the number of time it calls itself)
现在您可以看到:
boo = defFun3(foo,3)
boo =
@(x)foo{1}(foo{1}(foo{1}(x))) // <= now you know that boo is the function 'foo' called on itself 3 times.
boo=defFun3(foo,3)
boo=
@(x) foo{1}(foo{1}(foo{1}(x))/我的代码与您原来的代码非常相似。我冒昧地重命名了一些变量
直接方法:
对于单输入和单输出参数,可以使用与代码类似的直接方法:
function ftoN = fIterate(f, N)
ftoN = f;
for i = 2:N
ftoN = @(x) f(ftoN(x));
end
end
间接法:(可能更快)
这将是一个快得多,它也将为多个(但相同数量的)输入和输出工作
function ftoN = fIterate(f, N)
ftoN = @(varargin) fIterateLocal(f, N, varargin{:});
function varargout = fIterateLocal(f, N, varargin)
varargout = varargin;
for i = 1:N
[varargout{1:nargin-2}] = f(varargout{:});
end
end
end
例子:
这两种方法都应适用于此:
square = @(x) x^2;
square(2)
>> ans = 4
squaresquaresquare = fIterate(square, 3)
squaresquaresquare(3)
>> ans = 6561
后果:
直接方法将非常缓慢,并且还受到MATLAB的最大递归限制
的限制
timeit(@()feval(fIterate(@(X)X+1,400),0))
ans = 1.2160
间接方法将为您提供更多的速度和灵活性:
timeit(@()feval(fIterate(@(X)X+1,400),0))
ans = 0.0072
给出完整计算的结果很好,但我的印象是OP希望向新函数返回函数句柄
,而不仅仅是结果。@Hoki我不理解其中的问题为什么。我想关键是对`存储它<代码>的解释
it`可以是值或函数。但我认为否决这一点有点苛刻。否决票不是我。我正要投赞成票时,我尝试了你的答案,意识到它并不完整,但我肯定没有投反对票。这仍然是一个有效的部分答案,计算正确。因此,您正在寻找一个替代方案,不需要MuPAD。感谢所有人提供不同的答案@knedlsepp的解决方案正是我所需要的。不错,尽管我更喜欢在编辑之前使用间接方法,因为它在函数定义中留下了基函数的名称。由于您的编辑,它现在已经全部消失,但仍然可以完美地工作。哦,我这样做是为了使两个版本具有相同的界面。我认为,如果有人希望最终句柄具有良好的可读性,您的版本无论如何都是最好的!我喜欢你的间接方法这个想法,它和我的for循环方法一样快,增加了可读性。唯一的缺点是str2func对递归深度只有33的奇数限制。(当使用n=34
调用时,{,[]和(不能超过32的深度)嵌套的错误)谢谢@Hoki,我喜欢你的想法