2015-01-07 53 views
0

我有兩個Matlab函數f=fun1(x)f=fun2(x,y),它們非常相似,我想將它們集成到一個函數f=fun(x,y)中。在Matlab中將多個相似函數集成到一個函數中

對於第一函數I有

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)

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可能會非常大,這將是低效的。此外,它會完全破壞代碼的佈局。

+0

看看[本地功能](http://es.mathworks.com/help/matlab/matlab_prog/local-functions.html)和[嵌套功能](http://es.mathworks.com/幫助/ matlab/matlab_prog/nested-functions.html) –

回答

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

很好的答案......儘管[誤導](http://en.wiktionary.org/wiki/Houston,_we_have_a_problem):-P –

+0

看起來不錯,但我我不確定遞歸函數調用,函數(真正的問題)以for循環開始。我可能是錯的,但首先查看它,添加循環可能會以幾個嵌套for循環結束,這可以通過避免遞歸函數調用來避免。 – Nras

+0

@Hoki正如我在最後一段中試圖解釋的那樣,實際的問題有幾個相似之處,而不僅僅是一個。他們有時甚至在執行很多次的'for'循環中。因此,使用'switch-case'和'if-else'是不合適的。 – Adriaan

0

您可以通過複製代碼來避免檢查輸入參數數量narginN次。您將檢查一次,應該完成哪個計算並重復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循環開始,並通過添加重複代碼來刪除遞歸函數調用。