Some MATLAB tips (二)

來源:互聯網
上載者:User
 

tips4.關於MATLAB中內嵌函式,匿名函數,嵌套函數,M-檔案函數等的效率問題. 從根本上來說,,MATLAB函數分為兩類匿名函數(Anonymous Function)和M-檔案函數(M-File Function)。下面,我們從一個例子來說明各類函數地應用與效率比較。 問題描述:現在我要畫一個數值演算法的穩定地區,即要求出在複平面中矩形地區[-2,2;-30;30]內所有能使方程a(u)*x2+b(u)*x+c(u)=0的跟的模小於1的u的值並畫圖。 以匿名函數寫的程式如下:clear all
tic
% 係數;去掉分母后可以認為與原方程同解
a = @(u) exp(u)*(-1+exp(u)-2*u+u*exp(u));
b = @(u) -exp(u)*(-1-2*u+exp(2*u));
c = @(u) exp(2*u)*(-1+exp(u)-u);
% 求根公式
root1 = @(u) -b(u)+sqrt(b(u)^2-4*a(u)*c(u));
root2 = @(u) -b(u)-sqrt(b(u)^2-4*a(u)*c(u));
% 變數初始化
t = 1;
Result=zeros(400*600,1);
% 遍曆地區【-2:2;-30:30】;若點滿足條件,則儲存該值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
            && abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc 運行結果:Elapsed time is 86.485000 seconds.  M-檔案函數和嵌套函數程式:function R1 = root12(u)
% 用求根公式計算方程的兩個根
R1 = [ (-b(u)+sqrt(b(u)^2-4*a(u)*c(u)))/(2*a(u)+eps),
       (-b(u)-sqrt(b(u)^2-4*a(u)*c(u)))/(2*a(u)+eps) ];  function funa = a(u)   % Subfuntion
% 計算係數a(u)
    funa = exp(u)*(-1+exp(u)-2*u+u*exp(u));
end  function funb = b(u)   % Subfunction
% 計算係數b(u)
    funb = -exp(u)*(-1-2*u+exp(2*u));
end   function func = c(u)   % Subfunction
% 計算係數c(u)
    func = exp(2*u)*(-1+exp(u)-u);
endend clear all
tic
% 變數初始化
t = 1;
Result=zeros(400*600,1);
% 遍曆地區【-2:2;-30:30】;若點滿足條件,則儲存該值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        if (   min(abs(root12(ii + i*jj))<1) ~=0  )
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
end
plot(Result,'.')
toc 運行結果:Elapsed time is 36.328000 seconds.  不用函數直接把算式寫在M指令碼裡:clear all;tic% 變數初始化
t = 1;
Result=zeros(400*600,1);% 遍曆地區【-2:2;-30:30】;若點滿足條件,則儲存該值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        %if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
        %    && abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
        if (    abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                + sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj))))...
            &&  abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                - sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))))
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
endplot(Result,'.')toc 運行結果:Elapsed time is 26.578000 seconds. 結果是很明顯,直接將公式寫在M檔案裡比使用函數要快的多。這主要是因為調用函數時系統要做額外的進棧出棧和傳值工作。這裡沒有考慮內嵌函式(Inline Function),因為他是基於符號計算的,效率比匿名函數要低一些。但是將公式直接寫在M檔案了,程式的可讀性,重用性,可維護性都大大降低。折中的辦法也只能是對於調用次數很多的複雜的公式還是要做一個M檔案函數的,當然如果掉用次數小公式本身又比較簡單,用匿名函數也是自然的事情。     tips5.關於上述代碼的另一點小tip.  這一點是無意中發現的。將上述程式做如下小改動(細緻點看哦);  clear all;tic% 變數初始化
t = 1;
%Result=zeros(400*600,1);% 遍曆地區【-2:2;-30:30】;若點滿足條件,則儲存該值
for ii = -2:0.01:2;
    for jj = -30:0.1:30;       
        %if (   abs(root1(ii + i*jj)) < abs(2*a(ii + i*jj))...
        %    & abs(root2(ii + i*jj)) < abs(2*a(ii + i*jj))  )
        if (    abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                + sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj))))...
            &&  abs( exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj)))...
                - sqrt(((-exp(ii + i*jj)*(-1-2*(ii + i*jj)+exp(2*(ii + i*jj))))^2)...
                - 4*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))*(exp(2*(ii + i*jj))*(-1+exp(ii + i*jj)-(ii + i*jj)))))...
                < abs( 2*(exp(ii + i*jj)*(-1+exp(ii + i*jj)-2*(ii + i*jj)+(ii + i*jj)*exp(ii + i*jj)))))
            Result(t) = ii + i*jj;
            t = t+1;
        end
    end
endplot(Result,'.')toc 看出來沒有?其實就是把 %Result=zeros(400*600,1); 關掉了;把 && 改為 &. 接下來,看你的 Current Directory 視窗 上方有一個鍵上面有個小對號√ : 點一下進去回出現下面的介面,ZMY_StableArea_2.m 就是我們上面的指令碼的檔案名稱:  看到了吧!其實這是一個Code Check工具,一些不是太好的做法它會提示修改。例如上面的程式,如果所提示的第31行不做修改的話,運行結果為: Elapsed time is 63.984000 seconds. 這遠遠比做修改後的26.578000 seconds要慢!這其實容易理解,一個是為數組元素動態分配記憶體,一種是預分配,顯然預分配要快一些,這是典型的空間換時間的做法。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.