在Matlab中将多个类似函数集成到一个函数中

时间:2015-01-07 15:14:39

标签: matlab

我有两个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

。实际上fun1实际上是fun2的子函数。我想构建一个函数f=fun(x,y,method_number),如

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和{{的子函数1}}是fun2的子函数,其含义与上面相同。我不认为使用fun1switch-case是一个选项,因为if-else可能非常大,这将是低效的。此外,它会完全破坏代码的布局。

2 个答案:

答案 0 :(得分:3)

在你的情况下,你的每个函数都有不同数量的输入参数。如果是这种情况,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编译器足够聪明,不会打扰'无效'操作)。

答案 1 :(得分:0)

您可以通过复制代码来避免检查输入参数的数量nargin N - 次。您将检查一次,应该进行哪些计算并重复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循环开始,并通过添加重复代码来删除递归函数调用。