matlab 7 在工程上的應用eportfolio.lib.ksu.edu.tw/user/4/0/4000h237/repository/計概no ch...

87
MATLAB 7 在工程上的應用 3 函數與檔案

Upload: others

Post on 29-Sep-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

  • MATLAB 7 在工程上的應用

    第 3 章函數與檔案

  • 指數exp(x)sqrt(x)

    對數log(x)log10(x)

    複數*********abs(x)angle(x)conj(x) imag(x)real(x)

    指數;e x平方根;x

    自然對數;ln x常用(底數為 10)對數;log x = log10 x

    絕對值;|x|複數的角度共軛複數複數x的虛部複數x的實部

    表3.1–1 一些常見的數學函數

  • 數字

    ceil(x)fix(x)floor(x) round(x)sign(x)

    往 ∞ 四捨五入成最接近的整數往零四捨五入成最接近的整數

    往 -∞ 四捨五入成最接近的整數四捨五入成最接近的整數

    正負號函數:+1 如果 x > 0;0 如果 x = 0 ; -1 如果 x < 0

    表3.1–1 一些常見的數學函數(續…)

  • 圖3.1–1 複數a + ib的直角座標表示法以及極座標表示法。****

  • >>x = -3 + 4i;>>y = 6 - 8i;>>mag_x = abs(x)mag_x =

    5.0000>>mag_y = abs(y)mag_y =

    10.0000>>mag_product = abs(x*y)

    50.0000>>angle_x = angle(x)angle_x =

    2.2143>>angle_y = angle(y)angle_y =

    -0.9273>>sum_angles = angle_x + angle_ysum_angles =

    1.2870>>angle_product = angle(x*y)angle_product =

    1.2870

    ****複數的運算

  • 陣列的運算

    MATLAB 會自動將數字當作陣列來處理。例如,要計算5、7以及 15 的平方根,則輸入:

    >>x = [5,7,15];>>y = sqrt(x)y =

    2.2361 2.6358 3.8730

  • 測試了解程度

    T3.1-1 依題義: x = [5:20:85]; y = [10:30:130]; log(x.*y)=(log(x)+log(y)) 驗證正確性。

  • 函數引數的表示

    我們可以在書籍中寫下sin 2,但是在MATLAB中我們需要在 2 外面加上小括號(此時 2 叫做函數引數或者參數)。

    因此在MATLAB中要計算sin 2,我們輸入sin(2)。MATLAB的函數名稱之後要接上一對小括號包圍引數。

    在書籍中要表示陣列 x 中第二個元素的正弦值,則我們輸入sin[x(2)]。然而,在MATLAB中不能以這種方式使用中括號以及大括號,並且必須輸入sin(x(2))。

    (接下頁)

  • 函數引數的表示(承上頁)

    要計算sin(x 2 + 5),則要輸入sin(x.^2 + 5)。

    要計算sin(x+1) ,則要輸入sin(sqrt(x)+1)。

    使用函數當作另外一個函數的引數,我們稱之為函數合成。當輸入這類的算式時,記得要檢查優先權順序以及數字和括號的擺放位置。

    每一個左括號需要配對一個右括號。然而,此條件並不能保證算式一定正確。

    (接下頁)

  • 函數引數的表示(承上頁)

    另一個常見的錯誤就是使用例如sin2 x這樣的算式,此算式表達的意思是(sin x)2。在MATLAB中我們將此算式寫為 (sin(x))^2,而不是寫成 sin^2(x)、 sin^2x、sin(x^2)、或者sin(x)^2!

    MATLAB的三角函數運算所使用的角度為弳度。因此sin(5)計算出來的是5弳度的正弦值,而不是5°的正弦值。

    要在角度以及弳度之間轉換,可使用關係式qradians = (pi /180)qdegrees。

    更多相關資料請查詢課本第3-7~3-8頁

  • 三角函數

    cos(x)cot(x) csc(x)sec(x)sin(x)tan(x)反三角函數

    acos(x)acot(x)acsc(x)asec(x)asin(x)atan(x)atan2(y,x)

    餘弦函數;cos x餘切函數;cot x餘割函數;csc x正割函數;sec x正弦函數;sin x正切函數;tan x

    反餘弦函數;arccos x反餘切函數;arccot x反餘割函數;arccsc x反正割函數;arcsec x反正弦函數;arcsin x反正切函數;arctan x四象限反正切值

    表3.1–2 三角函數

  • 雙曲函數

    cosh(x)coth(x)csch(x)sech(x)sinh(x)tanh(x)反雙曲函數

    acosh(x) acoth(x) acsch(x) asech(x) asinh(x) atanh(x)

    雙曲餘弦函數

    雙曲餘切函數

    雙曲餘割函數

    雙曲正割函數

    雙曲正弦函數

    雙曲正切函數

    反雙曲餘弦函數

    反雙曲餘切函數

    反雙曲餘割函數

    反雙曲正割函數

    反雙曲正弦函數

    反雙曲正切函數

    表3.1–3 雙曲函數

  • 測試了解程度

    T3.1-4 依題義: x = [0:0.4:2*pi]; asin(x)+acos(x)-pi/2 驗證答案。

    T3.1-5依題義: x = [0:0.4:2*pi]; tan(2*x)-2*tan(x)./(1-tan(x).^2) 驗證答案。

  • 使用者定義之函數

    函數檔案中的第一列必須是函數定義列來起頭,此處會列出輸入以及輸出。此列也用來區分函數M檔以及腳本M檔。其語法如下:

    function [output variables] = name(input variables)

    我們注意到輸出變數以中括號來包圍,而輸入變數則是以小括號來包圍。function_name則要和所儲存的檔案名稱(具有.m這個副檔名)一致。

    更多相關資料請查詢課本第3-9~3-10頁

  • 使用者定義函數範例

    function z = fun(x,y)u = 3*x;z = u + 6*y.^2;

    注意到在每一列最後使用了分號。這能夠讓 u 以及 z 的值不要顯示出來。

    我們也要注意到陣列指數運算子(.^)的使用方式,這能夠讓函數接受 y 為一陣列。

    (接下頁)

  • 使用者定義函數範例(承上頁)

    以包括輸出引數的方式來呼叫此函數:

    >>z = fun(3,7)z =

    303

    此函數使用 x = 3 以及 y = 7 來計算 z。

    (接下頁)

  • 使用者定義函數範例(承上頁)

    而以不包括輸出引數並且嘗試存取函數的值的方式來呼叫此函數。你會看到下列的錯誤訊息。

    >>fun(3,7)ans =

    303>>z??? Undefined function or variable ’z’.

    (接下頁)

  • 使用者定義函數範例(承上頁)

    將輸入引數指派到另外一個變數:

    >>q = fun(3,7)q =

    303

    你可以在函數呼叫後放上一個分號來抑制輸出。

    例如,如果輸入q = fun(3,7);則只會計算q的值而不會顯示出來(因為程式碼中有加入分號)。

  • 對於函數fun,變數x以及y是局部的,所以除非你將這些值命名為x以及y然後傳送,否則在此工作空間之外是沒有辦法存取這兩個變數的值。變數u對於函數也是局部的。例如,

    >>x = 3;y = 7;>>q = fun(x,y);>>xx =

    3>>yy =

    7>>u??? Undefined function or variable ’u’.

  • 引數的順序是很重要的,而引數的名稱並沒有那麼重要:

    >>x = 7;y = 3;>>z = fun(y,x) z =303

    第二列的程式碼等效於 z = fun(3,7)。

    你可以使用陣列當作輸入引數:

    >>r = fun([2:4],[7:9])r =

    300 393 498

  • 函數有可能具有超過一個以上的輸出。將這些輸出包圍在中括號之內。例如,函數circle計算圓的面積A以及圓周C ,而給定其半徑當作輸入引數。

    function [A, C] = circle(r) % A 圓面積,C圓周長A = pi*r.^2;C = 2*pi*r;

    如果 r = 4,以下列方式呼叫函數。

    >>[A, C] = circle(4)A =

    50.2655C =

    25.1327

  • 函數可能沒有輸入引數以及輸出列表。

    例如,函數show_date計算並且儲存變數today中的日期,並且顯示出today的值。

    function show_datetoday = date %date 為指令

  • 1. 具有一個輸入以及一個輸出的函數

    function [area_square] = square(side)

    2. 當只有一個輸出時中括號是可以自由選取的

    function area_square = square(side)

    3. 具有一個輸出以及三個輸入

    function [volume_box] = box(height,width,length)

    4. 具有兩個輸出以及一個輸入

    function [area_circle,circumf] = circle(radius)

    5. 沒有輸出變數

    function sqplot(side)

    函數定義列範例

  • 函數範例

    function [dist,vel] = drop(g,vO,t);

    % 計算自由落體行經距離與速度

    %末速與行經距離為初速vO, 重力加速度g和時間t

    %的函數.

    vel = g*t + vO;

    dist = 0.5*g*t.^2 + vO*t;

    (接下頁)

  • 函數範例(承上頁)

    1. 在函數定義中所使用的變數名稱可以在函數呼叫時被使用,或者不使用:

    >>a = 32.2;>>initial_speed = 10;>>time = 5;>>[feet_dropped,speed] = . . .

    drop(a, initial_speed, time)

    (接下頁)

  • 函數範例(承上頁)

    2. 輸入變數之值在函數被呼叫前並不一定要在函數外部被指派:

    [feet_dropped, speed] = drop(32.2,10,5)

    3. 輸入以及輸出可以是陣列:[feet_dropped,speed]=drop(32.2,10,[0:1:5])

    此函數呼叫產生陣列feet_dropped以及speed,皆具有六個值,分別對應到陣列time中的六個時間的值。

  • 局部變數

    1. 在函數定義列中所給定的輸入變數名稱對於該函數是局部的。

    2. 這表示當你呼叫此函數時,可以使用其他的變數名稱來呼叫此函數。

    3. 除了在函數呼叫時某些在輸出變數列表中有使用到的變數名稱之外,在函數中的其他所有變數在函數

    執行完畢時都會被清除。

  • 全域變數

    指令global可以將某一變數宣告成為全域變數,也因此在宣告這些變數為全域變數時,這些變數的值能

    在基本工作區中取得,也能夠讓其他的函數取得。

    宣告a、x、以及q 成為全域變數的語法是:

    global a x q

    在任何函數或者基底工作區中,任何對於這些變數

    的指派,對於其他的函數也都是可取得的。

    更多相關資料請查詢課本第3-15~3-17頁

  • Example 3.2-1全域變數 function P =

    ideal_1(T,Vhat,R) P = R*T./Vhat;

    function P = ideal_2(T,Vhat)

    % 此處需要公升、大氣壓及莫耳單位!

    R = 0.08206; P = R*T./Vhat; % 注意: SI 公制 % R=8.314 J/mol-K

    function P = ideal_3(T,Vhat)

    global R P = R*T./Vhat;

    >>global R >>R = 0.08206; >>ideal_3([300,330],20)

  • function P = vdwaals_1(T,Vhat,R,a,b) P = R*T./(Vhat-b)-a./Vhat.^2;

    function P = vdwaals_2(T,Vhat) % 只針對氯(chlorine),此處需要公升、大氣壓及莫耳單位!! R = 0.08206; a = 6.49;b = 0.0562; P = R*T./(Vhat-b)-a./Vhat.^2;

    >>vdwaals_2(300,20) >>P ?? Undefined function or variable 'p'. >>P = vdwaals_2(300,20)

  • 找出函數的零點

    你可以使用fzero函數來找出單一變數函數的零點,此單一變數以x標記。此語法的一種形式為

    fzero(’function’, x0)

    其中function是一個字串,包含函數的名稱,並且x0是使用者所提供對於零點的猜測值。

    fzero這個函數傳回最靠近x0的x之值。找出了當函數跨過x軸的點,而不是剛好函數碰到軸的地方。

    例如,fzero(‘cos’,2)會傳回x = 1.5708。

  • 利用使用者定義函數使用fzero

    要使用fzero這個函數找尋更為複雜函數的零點,比較方便的方式是將此函數定義於函數檔。

    例如,如果y = x + 2e-x -3,則定義下列的函數檔:

    function y = f1(x)y = x + 2*exp(-x) - 3;

    (接下頁)

  • 圖3.2–1 畫出函數 y = x + 2e-x - 3 的圖形。

    由圖形可以看到兩個零點,一個靠近x = -0.5,另外一個靠近 x = 3。

    (接下頁)

  • 範例(承上頁)

    要找出靠近x = -0.5的零點,則

    >>x = fzero(‘f1’,-0.5)

    則答案為 x = -0.5881。

    更多相關資料請查詢課本第3-17~3-19頁

  • 最小化具有一個變數的函數

    函數fminbnd可以找出具有單一變數的函數的最小值,此單一變數以x標記。其語法的一種形式為

    fminbnd(’function’, x1, x2)

    其中function為包含函數名稱的字串。函數fminbnd傳回能夠使得函數在區間x1 ≤ x ≤ x2之內得到最小值的x。

    例如,fminbnd(‘cos’,0,4)會傳回的值為3.1416。

  • 使用 fminbnd 時,比較方便的方式是將此函數定義於函數檔。例如,如果 y = 1 - xe -x ,則定義下列的函數檔:

    function y = f2(x)y = 1-x.*exp(-x);

    在區間0 x 5內找出可以使得 y 發生最小值的x,則要輸入

    >>x = fminbnd(’f2’,0,5)

    答案為x = 1。要找出 y 的最小值,則輸入 type y = f2(x),結果為 y = 0.6321。

  • 一個函數具有一個或多個局部最小值以及一個全域

    最小值。

    如果給定的自變數範圍並不包含全域最小值,則

    fminbnd 函數並沒有辦法求出全域最小值。

    fminbnd 會找出在指定區間邊界上的最小值。

  • 圖3.2–2 畫出函數 y = 0.025x 5 - 0.0625x 4 - 0.333x 3 + x 2的圖形。

    此函數具有一個局部最小值以及一個全域最小值。在區間 [1, 4] 之內,最小值落在邊界上, x = 1。

  • 最小化多變數函數

    要找出具有一個以上變數的函數的最小值,則需要

    使用fminsearch函數。其語法的形式之一為

    fminsearch(’function’, x0)

    其中function是一個包含函數名稱的字串,向量x0是使用者所提供的猜測值。

  • 例如,要最小化函數f = xe-x2 - y2 ,則我們先把它定義在M檔中,並且使用元素為x(1)=x以及x(2) = y 的向量x。

    function f = f4(x)f = x(1).*exp(-x(1).^2-x(2).^2);

    假設我們所猜測的最小值是靠近x = y = 0。則對話為

    >>fminsearch(’f4’,[0,0])ans =

    -0.7071 0.000

    因此最小值會發生在x = -0.7071, y = 0。

    更多相關資料請查詢課本第3-19~3-22頁

  • Example 3.2-2 灌溉渠道的最佳化

    % L = b + 2d/sin % 梯形剖面 100 = db+ d^2/tan % b=(1/d)(100 – d^2/tan) % L =(100/d)-(d/tan)+(2d/sin) function L=channel(x) L = 100./x(1)-x(1)./tan(x(2)) + 2*x(1)./sin(x(2));

    x=fminsearch('channel',[20,1])

  • 灌溉渠道剖面. Figure 3.2–3

    3-92

  • 測試理解程度

    T3.2-1 依題:

    function y = f5(x)

    y = exp(-0.2*x).*sin(x+2)-0.1;

    %繪出函數圖利用fzero求解近似值,或簡單的嘗試應用 x 在 0與10之間求值. 程式為:

    fzero(‘f5’,0)

    fzero(‘f5’,4)

    fzero(‘f5’,6)

    %因此解為 x = 1.0187, 4.5334, 和 7.0066.

  • T3.2-2

    The function file is

    function y = f6(x)

    y = 1 + exp(-0.2*x).*sin(x+2);

    %繪出函數圖利用fminbnd求解近似值,或簡單的嘗試應用 x 在 0與10之間求值. 程式為:

    fminbnd(‘f6’,0)

    f6(ans)

    fminbnd(‘f6’,10)

    f6(ans)

    % 答案為 (x, y) = (2.5150, 0.4070) 和 (x, y) = (8.7982, 0.8312).

  • T3.2-3 由例題3.2-2.修改函數檔案將100 ft2以200 ft2 取代之. 函數變為:

    function L = channel(x)

    L = 200./x(1)-x(1)./tan(x(2))+2*x(1)./sin(x(2));

    %因類似例題3.2-2, 利用相同猜值;得

    x = fminsearch(‘channel’,[20,1])

    答案為d = 10.7457 ft 和 = 1.0472 radians, 或 60 deg

  • 函數握柄

    你可以在任何一個函數名稱之前加上@符號( at 符號)來對於任何函數建立一個函數握柄。如果想要的話,接下來

    你也可以對這個函數握柄命名,並且使用此函數握柄來參

    照此函數。例如,建立一個正弦函數的函數握柄,輸入

    >>sine_handle = @sin;

    其中sin_handle是使用者對於此函數握柄所選取的名稱。

    (接下頁)

  • 函數握柄(承上頁)

    此函數握柄的一般用途就是將函數以引數的方式

    傳遞到其他函數。例如,我們可以在區間0 x 6之內畫出sin x 的圖形,方法如下:

    >>plot([0:0.01:6],sine_handle([0:0.01:6]))

    (接下頁)

  • 函數握柄(承上頁)

    這對於畫出正弦函數而言是比較麻煩,但是此觀念

    可以幫助我們推展到建立一個一般用途的繪圖函數,

    此函數能夠接受其他函數當作輸入。例如,

    function x = gen_plot(fun_handle, interval)

    plot(interval, fun_handle, interval)

    你可呼叫此函數於區間 0 £ x £ 6之內畫出sin x,方法如下:

    >>gen_plot(sine_handle,[0:0.01:6])

    或者

    >>gen_plot(@sin,[0:0.01:6]) (接下頁)

  • 函數握柄(承上頁)*******WRONG

    例如,函數gen_plot可以如下列的使用方式,一般與函數握柄陣列一起使用以建立兩個子圖形,其中一個畫出正弦函

    數而另外一個則是畫出餘弦函數。

    fh(1) = @sin;

    fh(2) = @cos;

    for k = 1:2

    subplot(2,1,k)

    gen_plot(fh(k),[0:0.01:8])

    end

    更多相關資料請查詢課本第3-24~3-25頁

  • 呼叫函數的方法

    有四種方式可以採用或「呼叫」函數開始行動。分

    別為:

    1. 當字元字串對照到適當的函數M檔2. 為函數握柄的時候3. 為「嵌入」函數物件的時候4. 為一字串算式的時候。

    這些方式使用於fzero函數的範例如下,其中fun1是一個能夠計算y = x2 - 4的使用者定義函數。

    (接下頁)

  • 呼叫函數的方法(承上頁)

    1. 當字元字串對照到適當的函數M檔的時候,也就是

    function y = fun1(x)y = x.^2-4;

    函數也可以用以下的方式呼叫,來計算0 x 3範圍內的零點:

    >>[x, value] = fzero(’fun1’,[0, 3])

    (接下頁)

  • 呼叫函數的方法(承上頁)

    2. 為現存函數M檔的函數握柄的時候:>>[x, value] = fzero(@fun1,[0, 3])

    3. 為「嵌入」函數物件的時候:>>fun1 = ’x.^2-4’;>>fun_inline = inline(fun1);>>[x, value] = fzero(fun_inline,[0, 3])

    (接下頁)

  • 呼叫函數的方法(承上頁)

    4. 為一字串算式的時候:

    >>fun1 = ’x.^2-4’;

    >>[x, value] = fzero(fun1,[0, 3])

    或者也可以用以下方式

    >>[x, value] = fzero(’x.^2-4’,[0, 3])

    (接下頁)

  • 呼叫函數的方法(承上頁)

    此函數握柄的方法(方法2)是執行速度最快的方法,其次才是方法1。

    除了速度上的改進,另一個使用函數握柄的優點

    就是提供了對於子函數的存取,而這通常在定義

    它們的M檔之外是沒辦法看到的。

    更多相關資料請查詢課本第3-25~3-26頁

  • 函數的類型

    下列類型的使用者定義函數函數可以在M檔中建立。

    1. 主要函數是M檔中的第一個函數,並且通常包含主程式。在此檔案中接在主要函數之後的可以是許多子函

    數,這些子函數是做為主要函數的子程式。

    2. 通常主要函數是M檔內唯一能夠從MATLAB命令列或者其他M檔中呼叫的函數。可以使用M檔被定義的名稱來呼叫此函數。

    3. 我們通常將會把此函數的名稱以及其檔案命名成相同的名稱,但若是函數的名稱與檔案名稱不同,則要使

    用檔案的名稱來呼叫此函數。(接下頁)

  • 函數的類型(承上頁)

    4. 匿名函數能夠讓你建立一個簡單的函數而不需要為了這個函數建立一個M檔。

    5. 你可以使用MATLAB命令列或在其他的函數或者腳本檔中建立匿名函數。因此,匿名函數提供一個比較快速的

    方式讓你從MATLAB算式裡建立函數,而不需要建立、命名、以及儲存檔案。

    6. 子函數位於主要函數內,並且是由主要函數來呼叫。在單一的主要函數M檔內,可使用多個子函數。

    (接下頁)

  • 函數的類型(承上頁)

    1. 巢狀函數是定義在其他函數中的函數。巢狀函數可以幫助改善程式的可閱讀性,並且給予更多的彈性來存取

    M檔中的變數。

    2. 巢狀函數與子函數的差異為後者通常沒有辦法在其主要函數檔之外被存取。

    (接下頁)

  • 函數的類型(承上頁)

    3. 多載函數是會針對不同種類的輸入引數,產生不同反應的函數。這和任何物件導向的程式語言中的多載函數

    是類似的。

    4. 例如,可建立一個多載函數,使其處理整數輸入與倍精度浮點數輸入會得到不同的答案。

    5. 私有函數讓你能夠限制對於某一函數的存取。這些函數只能夠被母目錄中的 M 檔函數呼叫。

    更多相關資料請查詢課本第3-26~3-33頁

  • 函數函數這個名詞並不是一種特別的函數類型,其意思

    是指任何能夠接受其他函數當作引數的函數,例如fzero這個函數。

    你可以使用函數握柄將一個函數傳遞至另外一個函數。

  • 匿名函數

    匿名函數讓你能夠建立一個簡單的函數而不需要建立該函

    數的 M 檔。

    你可以在MATLAB命令列或者從其他函數或者其他腳本檔中建立匿名函數。由算式建立一個匿名函數的語法為

    fhandle = @(arglist) expr

    其中arglist是一個以逗號隔開的輸入引數清單,此清單被傳送至函數,並且expr是任何一行單一且有效的MATLAB算式。

    (接下頁)

  • 匿名函數(承上頁)

    要建立一個名稱為sq的簡單函數來計算某一數字的平方根,則輸入

    >>sq = @(x) x.^2;

    要改進可閱讀性,你可以將算式以括號包圍,譬如sq = @(x)(x.^2);。要執行此函數前必須輸入函數握柄的名稱,並在名稱後面接上以括號包圍的輸入引數。例如,

    >>sq([5,7])

    ans =

    25 49(接下頁)

  • 匿名函數(承上頁)

    你也許會認為這個特殊的匿名函數並沒有省下所耗費的時間,

    因為一共敲了九個鍵才輸入了sq([5,7]),比輸入[5,7].^2還多一個。

    然而,在這裡匿名函數能夠防止你忘記輸入代表陣列指數運算

    的句點(.)。

    對於需要許多按鍵輸入的更複雜函數,匿名函數是很有用的。

    (接下頁)

  • 匿名函數(承上頁)

    你可以將匿名函數的函數握柄傳遞至其他函數。例如,要求

    出多項式4x2 - 50x + 5在區間[-10, 10] 之內的最小值,則輸入

    >>poly1 = @(x) 4*x.^2 - 50*x + 5;>>fminbnd(poly1, -10, 10)ans =

    6.2500如果你並不想要再次使用這個多項式,你可以省略函數握柄

    的定義列並且輸入以下的指令代替

    >>fminbnd(@(x) 4*x.^2 - 50*x + 5, -10, 10)

  • 多個輸入引數

    你可以建立具有超過一個以上輸入的匿名函數。例如,要

    定義函數 (x 2 + y 2) ,則要輸入

    >>sqrtsum = @(x,y) sqrt(x.^2 + y.^2);

    接下來則要輸入

    >>sqrtsum(3, 4)ans =

    5

  • 另外一個例子,考慮定義一個平面的函數z = Ax + By。純量變數A 以及 B必須要在建立函數握柄時先指派其值。例如,

    >>A = 6; B = 4:

    >>plane = @(x,y) A*x + B*y;

    >>z = plane(2,8)

    z =

    44

  • 在另一個函數內呼叫函數

    匿名函數可以呼叫另一個函數來完成函數合成。考慮函數

    5 sin(x3)。此函數是由g(y) = 5 sin(y) 以及 f (x) = x 3這兩個函數合成。在下列的對話中函數的函數握柄為h,所呼叫的函數其函數握柄為f以及g。

    >>f = @(x) x.^3;>>g = @(x) 5*sin(x);>>h = @(x) g(f(x));>>h(2)ans =

    4.9468

  • 變數與匿名函數

    變數可以在匿名函數中以下列兩種方式出現:

    • 變數指定在引數清單中,例如f = @(x) x.^3;• 變數在算式的本體被指定,例如像是在plane = @(x,y)

    A*x + B*y中的變數A以及B。在這個情況下,於建立此函數時,於MATLAB中的函數攫取這些變數的值並且在函數握柄存在的期間一直保存這些值。在這個例子中,如果A以及B在函數握柄建立後被更動,這兩個變數與函數握柄相連的值卻不會被更動。這個特色有優點也有缺點,讀者們必

    須謹記於心。

    更多相關資料請查詢課本第3-29頁

  • 子函數

    一個函數M檔可能包含一個以上的使用者定義之函數。在此檔案中第一個定義的函數叫做主要函數,其名稱

    會和此M檔的檔名一樣。在此檔案中的其他函數叫做子函數。

    子函數通常只能被同一個檔案中的主要函數以及其他

    子函數「看到」;也就是說,沒有辦法被此檔案之外

    的其他程式或者函數呼叫。然而,這種限制卻可以使

    用函數握柄來移除。

  • 子函數(承上頁)

    通常我們首先建立主要函數的函數定義列以及其定義

    程式碼,且此檔案的名稱與函數的名稱相同。

    接下來建立每一個子函數,每一個子函數也有其自身

    的函數定義列以及定義程式碼。

    此函數的順序不重要,但是在此M檔中每一個函數名稱都必須是唯一的。

    更多相關資料請查詢課本第3-29~3-31頁

  • 呼叫函數的優先順序

    然而MATLAB檢查函數的順序是很重要的。當在M檔中的一個函數被呼叫,首先MATLAB會檢查看看此函數是否為一個內建函數,例如sin。

    如果不是,則檢查此函數是否為此檔案中的子函數,接

    下來則檢查是否為私有函數(位於呼叫函數的private子目錄中的函數M檔)。

    接下來MATLAB檢查是否為你的搜尋路徑上的標準M檔。

    (接下頁)

  • 呼叫函數的優先順序(承上頁)

    MATLAB在檢查私有函數以及標準M檔函數之前先檢查是否為子函數,你可以使用與其他現存的M檔具有相同名稱的子函數。

    這個特色讓你能夠任意命名子函數而不用擔心是否會與其

    他現存的函數具有一樣的名稱,所以你不需要取很長的函

    數名稱來避免發生衝突。

    這個特色能夠保護使用者不小心使用到其他的函數。

  • 下列的範例顯示MATLAB的M函數mean可以由你自己定義的平均來取代,這裡所給的值是均方根值。

    函數mean是一個子函數,而函數subfun_demo是一個主要函數。

    function y = subfun_demo(a)y = a - mean(a);%function w = mean(x)w = sqrt(sum(x.^2))/length(x);

    (接下頁)

  • 範例(承上頁)

    一個樣本對話如下。

    >>y = subfn_demo([4, -4])y =

    1.1716 -6.8284

    如果我們使用了MATLAB的M函數mean,我們會得到不同的答案;也就是,

    >>a=[4,-4];>>b = a - mean(a)b =

    4 -4

  • 因此子函數的用途可以讓你減少定義你的函數所使用的檔

    案數目。

    例如,如果前一個範例中的子函數mean不存在,我們必須要定義一個分開的M檔給我們的mean函數並且給予一個不同的名稱,以免與MATLAB中具有相同名稱的函數衝突。

    子函數通常只會被同一個檔案中的主要函數以及其他子函

    數看到。

    然而,我們可以使用一個函數握柄使得能夠自此M檔外存取這個子函數。

    更多相關資料請查詢課本第3-30~3-31頁

  • 巢狀函數

    使用MATLAB 7可以在另一個函數中定義一個或者更多的函數。以此方式定義的函數我們稱之為巢狀函數(築

    巢在主函數中)。你也可以在巢狀函數中再放入其他的

    函數。

    (接下頁)

  • 巢狀函數(承上頁)

    就像任何的M檔函數一樣,巢狀函數包含檔案函數的一般內容。

    然而,你必須記得永遠要用end敘述來終止巢狀函數。

    事實上,如果M檔包含至少一個巢狀函數,你必須在檔案中以 end 敘述來終止所有函數,包含子函數,不管是否包含任何巢狀函數。

  • 範例

    下列的範例建立了一個巢狀函數的函數握柄並且接下來傳

    遞此函數握柄到MATLAB函數fminbnd之中來找出拋物線的最小值的點。函數parabola建立並且傳回巢狀函數p的函數握柄f。此函數握柄被傳遞到fminbnd。

    function f = parabola(a, b, c)f = @p;

    function y = p(x)y = a*x^2 + b*x + c;

    endend (接下頁)

  • 範例(承上頁)

    在命令視窗中輸入

    >>f = parabola(4, -50, 5);>>fminbnd(f, -10, 10)ans =

    6.2500

    我們注意到函數p(x)可以在呼叫函數的工作空間中看到變數a、b,以及c。

  • 巢狀函數似乎看來與子函數一樣,但實際上並不一樣。

    巢狀函數具有下列兩個獨特的特性:

    1. 巢狀函數可以存取在築巢處內的所有函數的工作區。例如,一個變數具有被主要函數所指派的值,可以被築巢

    在主函數中任何階層的函數讀取或者覆寫。

    另外,在巢狀函數中被指派的變數可以被任何包含此函

    數的函數讀取或者覆寫。

    2. 如果你建立了一個巢狀函數的函數握柄,此函數握柄不只儲存了存取此巢狀函數所需要的資訊;還儲存了所有

    巢狀函數與包含此巢狀函數的函數共享的變數值。

    這表示這些變數持續存在於函數握柄所做的呼叫之間的

    記憶體中。

    更多相關資料請查詢課本第3-31~3-32頁

  • 私有函數

    私有函數位於具有特殊名稱private的子目錄中,並且只能被處在母目錄中的函數所看到。

    假設目錄rsmith列於MATLAB的搜尋路徑中。rsmith叫做private的子目錄所包含的函數只能被位於rsmith中的函數所呼叫。因為私有函數在母目錄rsmith之外是看不到的,所以名稱可以與其他目錄內的函數一樣。

    (接下頁)

  • 私有函數(承上頁)

    主要函數以及子函數可以用私有函數的方式實現。

    藉由建立子目錄的方式建立一個私有目錄,名稱為private,方法就如同在你的電腦上建立一個目錄或者資料夾的標準

    程序一樣,但是不要把這個私有目錄放在你的路徑上。

  • 輸入試算表檔案

    某些試算表程式將資料儲存於.wkl的格式。你可以使用以下指令M = wk1read(‘filename’)來將這些資料匯入MATLAB中並且儲存於矩陣M。

    指令A = xlsread(‘filename’)能夠將微軟Excel工作表檔案filename.xls匯入陣列A。而指令[A, B] = xlsread(‘filename’)能夠將所有的數值資料匯入陣列A中以及所有的文字資料匯入胞陣列B中。

  • 匯入精靈

    要匯入 ASCII 資料,你必須知道這些資料在檔案中是什麼樣的格式。

    例如,許多ASCII 資料檔案使用固定的(或者一致的)列以及行格式。

    (接下頁)

  • 匯入精靈(承上頁)

    對於這些檔案,你必須知道下列的事項。

    • 每一列中有多少項資料?

    • 這些資料是數值、文字字串、函數還是這兩種的混合?

    • 每一列或者每一行具有描述性的文字標題嗎?

    • 使用哪一種字元當作定界符?也就是用來在每一列中分隔每一項資料的字元。定界符我們也稱之為行分隔符。

    (接下頁)

  • 匯入精靈(承上頁)

    你可以使用匯入精靈來匯入許多類型的ASCII格式資料,包括在剪貼簿上的資料。注意到當你使用匯入精靈來建立在

    MATLAB工作區中的變數時,這個動作會覆寫任何已經存在於工作空間中具有相同名稱的變數,而且不會有任何的警告

    訊息。

    匯入精靈會顯示一系列的對話框,讓使用者能夠:

    1. 指定想要匯入的檔案名稱2. 指定該檔案中所使用的定界符3. 選取你想要匯入的變數

  • 圖3.4–1 匯入精靈的第一個螢幕。

    更多相關資料請查詢課本第3-34~3-35頁

  • HW03

    3-9、 3-10、 3-15、 3-18、 3-24