【问题标题】:Integration of multiple similar functions into one function in MatlabMatlab中将多个相似函数集成为一个函数
【发布时间】:2015-01-08 00:09:15
【问题描述】:

我有两个非常相似的 Matlab 函数 f=fun1(x)f=fun2(x,y),我想将它们集成到一个函数 f=fun(x,y)

对于我的第一个功能

function f=fun1(x)

N=1000; % Some large number.

for j=1:N
    f=x^2;
end

对于第二个功能

function f=fun2(x,y)

N=1000; % Some large number.

for j=1:N
    f=x^2;
    f=f+y;
end

。所以实际上fun1fun2 的一个子函数。我想构造一个函数f=fun(x,y,method_number)like

function f=fun(x,y,method_number)

N=1000; % Some large number.

for j=1:N
    f=x^2; % If method_number==1 run only this command....
    f=f+y; % If method_number==2 run also this command.
end

这只是我要解决的问题的一个简短的简化示例。我真正的问题是我有三个长函数f=fun1(x,y,z)f=fun2(x,y)f=fun3(x) 有几个相似之处,其中fun3fun2 的子函数,fun2fun1 的子函数与上面的意思相同。我不相信在任何地方都使用switch-caseif-else 是一种选择,因为N 可能非常大,这将是低效的。此外,它会完全破坏代码的布局。

【问题讨论】:

标签: matlab


【解决方案1】:

在您的情况下,您的每个函数似乎都有不同数量的输入参数。如果是这种情况,matlab 函数nargin 可以检测到,您不必指定额外的method 参数。

例如:

function f = fun(x,y,z)

switch nargin
    case 1
        f = x.^2;            %// run only if ONE argument was specified

    case 2
        f = fun(x) + y;      %// run only if TWO arguments were specified

    case 3
        f = fun(x,y) ./ z ;  %// run only if THREE arguments were specified

    otherwise
        disp('Houston, we have a problem !!') ; %// run if NO or more than 3 arguments were specified
end

你可以用一个参数调用f,两个或三个都没有问题,Matlab只会执行正确数量的参数对应的函数。

该函数在使用 3 个参数传递时,可以调用自身以计算具有 2 个参数的部分(它可以调用自身以从第一个参数计算部分)。


案例二:如果递归真的不能跳出循环,经典的if ... then就行了:

function f = fun(x,y,z)

if nargin == 3
        threeArgs = true ;
        twoArgs   = true ;
elseif nargin == 2
        threeArgs = false ;
        twoArgs   = true ;
elseif nargin == 1
        threeArgs = false ;
        twoArgs   = false ;
end

for it=1:1e6
    f = x.^2; %// If method_number==1 run only this command....
    %// ... other computations
    if twoArgs
        f = f + y ; %// If method_number==2 run also this command.
        %// ... other computations
        if threeArgs
            f = f ./z ; %// If method_number==3 run also this command.
            %// ... other computations
        end
        %// ... other computations only relevant to f(x,y)
    end
    %// ... other computations only relevant to f(x)
end

这将完全排除递归并确保最少的计算次数。


现在我意识到这看起来有点笨拙的代码,你要求一个没有if ... thenswitch 的解决方案。根据您的计算,有一种方法可以避免任何ifswitch,但可能不适用于所有情况。

想法是将invariant 运算符分配给yz,以防它们未被调用。

例子:

function f = fun(x,y,z)

if nargin < 3 ; z = 1 ; end
if nargin < 2 ; y = 0 ; end

for it=1:1e6
    f = x.^2; 
    %// ... other computations just based on X

    f = f + y ; %// This always run, but if "y" wasn't specified, it does not modify the result (f+0=f)
    %// ... other computations

    f = f ./z ; %// This always run, but if "z" wasn't specified, it does not modify the result (f./1=f)
    %// ... other computations

end

这避免了代码中的任何流程分支,但我只会在简单的情况下保留此方法,因为无论情况如何,计算总是完成(尽管可能某些 JIT 编译器足够聪明,不会费心去做“无效”)操作)。

【讨论】:

  • 不错的答案...尽管misquote :-P
  • 看起来不错,但我不确定递归函数调用,其中函数(在真正的问题中)以 for 循环开始。我可能错了,但首先看一下,添加循环可能会以几个嵌套的 for 循环结束,这可以通过避免递归函数调用来避免。
  • @Hoki 正如我在上一段中试图解释的那样,实际问题有几个相似之处,而不仅仅是一个。而且它们有时甚至在一个for 循环中,该循环被执行了很多次。因此,使用switch-caseif-else 是不合适的。
  • @Adriaan。如果使用此方法存在缺陷,那么您需要提供有关函数结构的更多详细信息,哪些是常见的,哪些不是,哪些在循环中,哪些不是。否则我只会在黑暗中刺伤。此外,在参数 2 和 3 的情况下,如果 x 已经在第一步中计算(即使它进行了循环),则不必在接下来的循环中重新计算,只需使用 x(i)在这些循环中。
  • @Adriaan,我修改了答案以提供其他选项
【解决方案2】:

您可以通过复制代码避免检查输入参数的数量narginN-times。您将检查一次,应该完成哪个计算并重复N 次。在此示例中,for 循环是重复的代码。在某种程度上,这可能没问题。

function f = fun(x, y, z)
N = 1000;

switch nargin

    %// Do something if only x is given
    case 1
    for j = 1:N
        f = x.^2;
    end

    %// Do something else if only x and y are given
    case 2
    for j = 1:N
        f = x.^2 + y;
    end

    %// Do something else if x, y and z are given
    case 3
    for j = 1:N
        f = x.^2 + y - z;
    end

    otherwise
        error('Use fun.m with 1, 2 or 3 arguments only!');
end
end

这是 Hoki 答案的变体。事实上,我从添加 for 循环开始,并通过添加重复代码来删除递归函数调用。

【讨论】:

    猜你喜欢
    • 2017-06-22
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 2020-11-19
    • 2020-12-15
    • 2016-08-22
    • 1970-01-01
    相关资源
    最近更新 更多