You are on page 1of 83

MATLAB程式設計入門

──在工程上的應用
Lesson 5
使用者定義函式
Instructor:陳彥銘
好的編寫程式技巧
盡可能將大型程式分解成子計畫的函式,如此做
的好處包括:函式的獨立測試、函式的重複使用
,以及避免無心錯誤所帶來的副作用。

第6章 使用者定義函式 第293頁


6.1 MATLAB函式介紹
function [outarg1, outarg2, ...]
= fname(inarg1, inarg2, ...)
% H1 comment line
% Other comment lines
...
(Executable code)
...
(return)
(end)

第6章 使用者定義函式 第293頁


6.2 MATLAB的變數傳遞:傳值法
函式名稱和儲存檔名須完全相同, 如一名為
My_fun的函式, 應儲存在My_fun.m的檔案中。

MATLAB程式使用傳值法(pass-by-value)進行
程式與函式之間的聯繫。當程式呼叫函式時,
MATLAB便複製實際引數並傳遞給函式使用。這
種複製行為是很關鍵的,它意味著即使函式更改
了輸入引數值,也不會影響到呼叫程式的原始資
料。這種特性可以防止在函式中無意間修改輸入
引數的錯誤,而影響到呼叫程式的原始變數值。

第6章 使用者定義函式 第299頁


範例6.1 直角座標與極座標的轉換

第6章 使用者定義函式 第301頁


範例6.1 直角座標與極座標的轉換
在平面上一點的位置可以由直角座標(x, y)表示,
或是極座標(r, θ)表示,如圖6.3所示。這兩個座標
系統間的轉換關係式為︰

x  r cos  (6-1)
y  r sin  (6-2)
r  x2  y 2 (6-3)
y
  tan 1
(6-4)
x

第6章 使用者定義函式 第300-301頁


範例6.1 直角座標與極座標的轉換
請寫出兩個函式rect2polar及polar2rect,
除了把直角座標轉換成極座標,也可以把極座標
轉換成直角座標,其中角度θ以度數表示。

第6章 使用者定義函式 第301頁


範例6.1 直角座標與極座標的轉換-解
我們將使用解決問題的標準流程來建立這些函式
。請注意MATLAB 的三角函數是使用弳度計算,
因此我們必須把度數轉成弳度再代入三角函數;
反之,三角函數計算結果的角度也必須從弳度換
算成度數。度數與弳度間的轉換關係式為:
180° = π 弳度 (6-5)

第6章 使用者定義函式 第301頁


範例6.1 直角座標與極座標的轉換-解
3. 設計演算法。
 這些函式非常簡單,所以我們能夠直接寫出它們的虛
擬碼。polar2rect函式的虛擬碼為︰
x ← r * cos(theta * pi/180)
y ← r * sin(theta * pi/180)
 rect2polar函式的虛擬碼將使用可以在平面四個象
限執行的atan2函式(你可以利用 MATLAB 的說明瀏
覽器查詢這個函數的使用方法)。
r ← sqrt(x.^2 + y.^2)
theta ← 180/pi * atan2(y,x)

第6章 使用者定義函式 第302頁


範例6.1 直角座標與極座標的轉換-解
4. 把演算法變成MATLAB 敘述式。
 polar2rect函式的 MATLAB 程式碼顯示如下:

function [x, y] = polar2rect(r,theta)


%Polar2rect Convert rectangular to polar coordinates
%(H1註解列, 可供look for指令查詢)
% Function Polar2rect accepts the polar coordinates
% (r,theta), where theta is expressed in degrees,
% and converts them into the rectangular coordinates
% (x, y).
%
% Calling sequence:
% [x, y] = polar2rect(r,theta)

第6章 使用者定義函式 第302頁


範例6.1 直角座標與極座標的轉換-解
% Define variables:
% r -- Length of polar vector
% theta -- Angle of vector in degrees
% x -- x-position of point
% y -- y-position of point
(H1至第一個空白行為止是help指令可以查詢到的資料)
% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/01/10 S. J. Chapman Original code

x = r * cos(theta * pi/180);
y = r * sin(theta * pi/180);

第6章 使用者定義函式 第303頁


範例6.1 直角座標與極座標的轉換-解
 rect2polar函式的 MATLAB 程式碼顯示如下:

function [r, theta] = rect2polar(x,y)


%Rect2polar Convert rectangular to polar coordinates
% Function Rect2polar accepts the rectangular coordinates
% (x, y) and converts them into the polar coordinates
% (r,theta), where theta is expressed in degrees.
%
% Calling sequence:
% [r, theta] = rect2polar(x,y)

第6章 使用者定義函式 第303頁


範例6.1 直角座標與極座標的轉換-解
% Define variables:
% r -- Length of polar vector
% theta -- Angle of vector in degrees
% x -- x-position of point
% y -- y-position of point

% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/01/10 S. J. Chapman Original code

r = sqrt( x.^2 + y.^2 );


theta = 180/pi * atan2(y,x);

第6章 使用者定義函式 第303頁


範例6.1 直角座標與極座標的轉換-解
 請注意這些函式都加上了說明文字,所以它們能在
MATLAB 的說明系統中或使用lookfor指令查詢這些
函式的說明。

5. 測試程式。
 為了測試這些函式,我們將在 MATLAB 的指令視窗直
接執行這些函式。我們將使用在中學已熟悉的3-4-5直
角三角形來執行這些函式,此三角形內最小角度約為
36.87˚。我們也將在直角座標的四個象限內分別測試這
些函式,以確保正確的座標轉換。

第6章 使用者定義函式 第303-304頁


範例6.1 直角座標與極座標的轉換-解

» [r, theta] = rect2polar(4,3)


r =
5
theta =
36.8699
» [r, theta] = rect2polar(-4,3)
r =
5
theta =
143.1301

第6章 使用者定義函式 第304頁


範例6.1 直角座標與極座標的轉換-解

» [r, theta] = rect2polar(-4,-3)


r =
5
theta =
-143.1301
» [r, theta] = rect2polar(4,-3)
r =
5
theta =
-36.8699

第6章 使用者定義函式 第304頁


範例6.1 直角座標與極座標的轉換-解

» [x, y] = polar2rect(5,36.8699)
x =
4.0000
y =
3.0000
» [x, y] = polar2rect(5,143.1301)
x =
-4.0000
y =
3.0000

第6章 使用者定義函式 第304頁


範例6.1 直角座標與極座標的轉換-解

» [x, y] = polar2rect(5,-143.1301)
x =
-4.0000
y =
-3.0000
» [x, y] = polar2rect(5,-36.8699)
x =
4.0000
y =
-3.0000

第6章 使用者定義函式 第304頁


範例 6.2 資料排序
在很多科學與工程的應用領域,常需要輸入一組
隨機的資料,並以遞增順序(從小到大),或遞
減順序(從大到小)來排列這組資料。例如,假
設你是一位動物學家,從事一大群動物的研究工
作,想要找出這群動物中數量最多的前百分之五
。處理這個問題最直接的方法就是把這群動物的
數量依遞增順序來排列,並選取排列結果最多的
百分之五即可。

第6章 使用者定義函式 第305頁


範例 6.2 資料排序
資料依遞增順序或遞減順序來排列似乎是一件很
簡單的工作。畢竟,我們經常處理這一類的事情
。對我們來說,把資料(10, 3, 6, 4, 9)排序成為
(3, 4, 6, 9, 10)應該是件簡單的事情。我們是如
何做到的?我們首先需要搜尋輸入資料清單(10,
3, 6, 4, 9)的最小值(3),然後再搜尋剩下的輸
入資料清單(10, 6, 4, 9),以找出下一個最小值
(4),並依此類推,直到完成清單內所有數字的
排序。

第6章 使用者定義函式 第305頁


範例 6.2 資料排序
我們在這個例子將限制使用最簡單的演算法,說
明資料排序的概念。最簡單的演算法稱為選擇排
序法(selection sort)。它只是將上述人工排序方
式應用到電腦程式設計。
選擇排序法的基本邏輯演算為︰
1. 搜尋需要排序的數字清單,以找出這其中的最小值,
並將此最小值與數列的第一個數值交換位置。假設在
數列的第一個位置已經是最小值,就不執行交換位置
的動作。

第6章 使用者定義函式 第305頁


範例 6.2 資料排序
2. 搜尋數列中第二個位置到最後一個位置的數字,以找出整個數列
中的次小值,並將找到的次小值與數列的第二個數字交換位置。
假設數列的第二個位置的數字已經是次小值,就不執行交換位置
的動作。
3. 搜尋數列中第三個位置到最後一個位置的數字,以找出整個數列
中的第三小值。並將找到的第三小值與數列的第三個數字交換位
置。假設數列的第三個位置的數字已經是第三小值,就不執行交
換位置的動作。
4. 重複這個步驟,直到在數列中倒數第二個位置已處理完畢。當數
列中的倒數第二個位置已經被比較排序後,整個排序工作就算大
功告成了。
 請注意如果我們需要排序N個數字,這種排序法將需要進
行N-1 次的資料搜尋,以完成整個資料的排序動作。

第6章 使用者定義函式 第305-306頁


範例 6.2 資料排序
這個選擇排序過程可以使用圖6.4 說明。
因為資料清單裡有5 個數值要排序,我們將進行4
次資料搜尋。第一次搜尋整筆資料找出最小值為3
,所以將3 與第一個位置的 10 交換位置。第二次
搜尋位置 2 到位置5 的資料,發現最小值為4,因
此將4 與第二個位置的10 交換位置。第三次搜尋
位置 3 到位置 5 的資料,發現最小值為 6,而最
小值 6 已在第三個位置, 所以不進行交換動作。
最後,第四次搜尋位置4 到位置5 的最小值,發現
最小值為9,因此將9 與第四個位置的10 交換位置
,這樣便完成了整筆資料的排序。

第6章 使用者定義函式 第306頁


範例 6.2 資料排序

第6章 使用者定義函式 第306頁


編寫程式的陷阱
選擇排序法是最容易理解的排序演算法,但在計
算上卻很沒效率。它不應該用於大量資料集的排
序(譬如說超過1000 筆資料)。多年來,電腦科
學家已經發展出更有效率的排序演算法。
MATLAB 的內建函式sort 及sortrows 是兩個
非常有效率的排序函式,可應用於處理實際的排
序問題。

第6章 使用者定義函式 第307頁


範例 6.2 資料排序-解
這個程式必須要求使用者輸入資料、排序資料,
並輸出被排序過的資料。這個問題的設計流程如
下:
1. 敘述問題。
 我們還沒指定排序資料的類型為何。如果資料是數值
資料,則問題可以敘述如下︰
• 開發一個程式,可以從指令視窗讀取任意數量的數值資
料,使用單獨的排序函式依遞增的順序排列這組資料,
並把排序完成的資料輸出到指令視窗。

第6章 使用者定義函式 第307頁


範例 6.2 資料排序-解
2. 定義輸入和輸出。
 這個程式的輸入是使用者從指令視窗鍵入的數值資料
。而程式的輸出是輸出到指令視窗完成排序的資料。
3. 設計演算法。
 這個程式可以被分解成三個主要步驟:
將輸入資料儲存到一個陣列
將資料依遞增順序排列
輸出排序完成的資料

第6章 使用者定義函式 第307頁


範例 6.2 資料排序-解
 第一個步驟是讀取資料。我們必須提示使用者輸入資
料的筆數,然後再讀取資料值。因為已經知道需要讀
取多少筆輸入資料,適合使用for迴圈來讀取資料。詳
細的虛擬碼顯示如下︰

提示使用者輸入資料的筆數(nvals)
讀取資料筆數的值
預先配置一個輸入陣列
for ii = 1:nvals
提示輸入下一筆資料
讀取資料
end
第6章 使用者定義函式 第308頁
範例 6.2 資料排序-解
 接下來我們需使用單獨的函式來排序這些資料。我們
將需要搜尋整個資料nvals-1次,以找出每次剩餘數
值中的最小值。我們將使用一個指標來標示每次搜尋
到的最小值在數列中的位置。假如找到的最小值不在
該次搜尋數列的第一個位置,就把最小值交換到該次
搜尋數列的第一個元素。詳細的虛擬碼如下︰
for ii = 1:nvals-1
% 找出 a(ii) 到 a(nvals)之中的最小值
iptr ← ii
for jj == ii+1 : nvals
if a(jj) < a(iptr)
iptr ← jj
end
end
第6章 使用者定義函式 第308頁
範例 6.2 資料排序-解
% 現在 iptr 指到最小值
% 假如 iptr ~= ii 就交換 a(iptr) 和 a(ii)
if ii ~= iptr
temp ← a(i)
a(i) ← a(iptr)
a(iptr) ← temp
end
end
 最後的步驟是輸出被排序好的資料。這個步驟的虛擬
碼不需要再進一步細分。而最後的虛擬碼就是結合這
三個步驟:讀取、排序和輸出結果。

第6章 使用者定義函式 第308頁


範例 6.2 資料排序-解
4. 把演算法變成MATLAB 敘述式。
 以下是選擇排序函式的 MATLAB 程式碼:

function out = ssort(a)


%SSORT Selection sort data in ascending order
% Function SSORT sorts a numeric data set into
% ascending order. Note that the selection sort
% is relatively inefficient. DO NOT USE THIS
% FUNCTION FOR LARGE DATA SETS. Use MATLAB's
% "sort" function instead.

第6章 使用者定義函式 第308-309頁


範例 6.2 資料排序-解
% Define variables:
% a -- Input array to sort
% ii -- Index variable
% iptr -- Pointer to min value
% jj -- Index variable
% nvals -- Number of values in "a"
% out -- Sorted output array
% temp -- Temp variable for swapping

% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/02/10 S. J. Chapman Original code

第6章 使用者定義函式 第309頁


範例 6.2 資料排序-解

% Get the length of the array to sort


nvals = length(a);

% Sort the input array


for ii = 1:nvals-1
% Find the minimum value in a(ii) through a(n)
iptr = ii;
for jj = ii+1:nvals
if a(jj) < a(iptr)
iptr = jj;
end
end

第6章 使用者定義函式 第309頁


範例 6.2 資料排序-解

% iptr now points to the minimum value, so swap a(iptr)


% with a(ii) if ii ~= iptr.
if ii ~= iptr
temp = a(ii);
a(ii) = a(iptr);
a(iptr) = temp;
end
end

% Pass data back to caller


out = a;

第6章 使用者定義函式 第309頁


範例 6.2 資料排序-解
 呼叫選擇排序函式的程式如下:

% Script file: test_ssort.m


%
% Purpose:
% To read in an input data set, sort it into
% ascending order using the selection sort o
% algorithm, and twrite the sorted data to the
% Command window. This program calls function
% "ssort" to do the actualsorting.

第6章 使用者定義函式 第309-310頁


範例 6.2 資料排序-解

%
% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/02/10 S. J. Chapman Original code
%
% Define variables:
% array -- Input data array
% ii -- Index variable
% nvals -- Number of input values
% sorted -- Sorted data array

第6章 使用者定義函式 第310頁


範例 6.2 資料排序-解
% Prompt for the number of values in the data set
nvals = input('Enter number of values to sort: ');

% Preallocate array
array = zeros(1,nvals);

% Get input values


for ii = 1:nvals

% Prompt for next value


string = ['Enter value ' int2str(ii) ': '];
array(ii) = input(string);
end

第6章 使用者定義函式 第310頁


範例 6.2 資料排序-解

% Now sort the data


sorted = ssort(array);

% Display the sorted result.


fprintf('\nSorted data:\n');
for ii = 1:nvals
fprintf(' %8.4f\n',sorted(ii));
end

第6章 使用者定義函式 第310頁


範例 6.2 資料排序-解
5. 測試程式。
 為了測試這個程式,我們將建立一組輸入資料來執行
這個程式。這組資料應該包含正數與負數,而且最少
有兩個相同數值,以確定程式是否能在這些條件下正
常運作。
» test_ssort
Enter number of values to sort: 6
Enter value 1: -5
Enter value 2: 4
Enter value 3: -2
Enter value 4: 3
Enter value 5: -2
Enter value 6: 0

第6章 使用者定義函式 第310-311頁


範例 6.2 資料排序-解
Sorted data:
-5.0000
-2.0000
-2.0000
0.0000
3.0000
4.0000
 程式對我們的測試資料提供了正確的答案。請注意這
個程式對正數、負數及重複的數字皆能順利排序。

第6章 使用者定義函式 第311頁


6.3 選擇性引數
nargin──傳回用來呼叫函式的實際輸入引數數
目。
nargout──傳回用來呼叫函式的實際輸出引數數
目。
nargchk──假如用來呼叫函式的引數太少或是太
多,此函式將傳回一個標準的錯誤訊息。
error──當引數發生嚴重錯誤時,顯示此錯誤訊
息,並停止產生錯誤函式的執行。

第6章 使用者定義函式 第311-312頁


6.3 選擇性引數
warning──當引數發生輕微錯誤時,顯示此警告
訊息,而函式仍可以繼續執行。
inputname──傳回對應輸入引數清單特定次序
的實際變數名稱。

第6章 使用者定義函式 第312頁


6.3 選擇性引數
Ex:
msg = nargchk(min_args,max_args,nargin)
error(msg)

 若nargin落在min_args與max_args之外, msg為一內
建標準錯誤訊息
 若nargin落在min_args與max_args之間(包含),
msg為空字串
 error()若輸入標準錯誤訊息, 則程式停止並印出錯誤
訊息, 若輸入空字串, 則程式繼續執行

第6章 使用者定義函式 第312頁


範例6.3 使用選擇性引數
我們將舉例說明選擇性引數的應用,建立一個函
式接受輸入直角座標 (x, y),並將之轉換為大小與
角度所構成的極座標,其中,角度單位為度數。
此函式將接受x和y兩個輸入引數,但是,如果只
有輸入一個引數,則函式將會假設y值為0,並且
繼續完成轉換的計算。正常情況下,函式將傳回
距離與角度兩個數值,但如果敘述式只有一個輸
出引數,它只會傳回距離值。

第6章 使用者定義函式 第313頁


範例6.3 使用選擇性引數
這個函式顯示如下:
function [mag, angle] = polar_value(x,y)
%POLAR_VALUE Converts (x,y) to (r,theta)
% Function POLAR_VALUE converts an input
% (x,y)value into (r,theta), with theta in
% degrees.It illustrates the use of optional
% arguments.

第6章 使用者定義函式 第313頁


範例6.3 使用選擇性引數
% Define variables:
% angle -- Angle in degrees
% msg -- Error message
% mag -- Magnitude
% x -- Input x value
% y -- Input y value (optional)

% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/03/10 S. J. Chapman Original code

第6章 使用者定義函式 第313-314頁


範例6.3 使用選擇性引數
% Check for a legal number of input
arguments.
msg = nargchk(1,2,nargin);
error(msg);

% If the y argument is missing, set it to 0.


if nargin < 2
y = 0;
end

第6章 使用者定義函式 第314頁


範例6.3 使用選擇性引數
% Check for (0,0) input arguments, and print
% out a warning message.
if x == 0 & y == 0
msg = 'Both x and y are zero: angle is
meaningless!';
warning(msg);
(與error()不同, warning()只顯示警告訊息, 但不會中斷程式執行)
end

第6章 使用者定義函式 第314頁


範例6.3 使用選擇性引數
% Now calculate the magnitude.
mag = sqrt(x.^2 + y.^2);

% If the second output argument is present,


% calculate angle in degrees.
if nargout == 2
angle = atan2(y,x) * 180/pi;
end

第6章 使用者定義函式 第314頁


範例6.3 使用選擇性引數
我們將在指令視窗反覆測試這個函式。首先嘗試
使用過少或過多的引數來呼叫這個函式。

» [mag angle] = polar_value


??? Error using ==> polar_value
Not enough input arguments.

» [mag angle] = polar_value(1,-1,1)


??? Error using ==> polar_value
Too many input arguments.

第6章 使用者定義函式 第314頁


範例6.3 使用選擇性引數
 函式對於這兩種情況都能提供正確的錯誤訊息。接著,我
們將嘗試使用一到二個輸入引數,來呼叫這個函式。

» [mag angle] = polar_value(1)


mag =
1
angle =
0
» [mag angle] = polar_value(1,-1)
mag =
1.4142
angle =
-45

第6章 使用者定義函式 第314-315頁


範例6.3 使用選擇性引數
函式對於這兩種情況也都能提供正確的答案。然
後我們將使用一到二個輸出引數,來嘗試呼叫這
個函式。

» mag = polar_value(1,-1)
mag =
1.4142
» [mag angle] = polar_value(1,-1)
mag =
1.4142
angle =
-45
第6章 使用者定義函式 第315頁
範例6.3 使用選擇性引數
函式對於這兩種情況也提供了正確的答案。最後,
我們將嘗試以x和y值都是0來呼叫這個函式。

?[mag angle] = polar_value(0,0)


Warning: Both x any y are zero: angle is meaningless!
> In d:\book\matlab\chap6\polar_value.m at line 32
mag =
0
angle =
0
在這種情況下,函式顯示了警告訊息之後,仍然繼
續執行。
第6章 使用者定義函式 第315頁
6.4 使用全域記憶體分享資料
全域變數是藉由global 敘述來產生,其敘述形式
如下:

global var1 var2 var3 ...

一變數若宣告為全域變數,將存放在全域記憶體內
。若同一名稱的變數在別的函數內也被宣告為全
域記憶體, 則這個變數將對應到同一個記憶體位
址。因此全域變數可以用來分享不同函式間的資
料。

第6章 使用者定義函式 第317頁


好的編寫程式技巧
以大寫字母宣告全域變數,使它容易與區域變數
區分。

使用全域變數時,在函式的初始設定區塊和第一
個可執行敘述式之間,宣告所有的全域變數。

你可以使用全域記憶體,在程式的函式之間傳遞
大量資料。

第6章 使用者定義函式 第318頁


範例6.4 亂數產生器
在真實的世界裡,我們很難進行一個完美的量測
,因為實際量測總有一些量測的雜訊。對於實際
系統的操控而言,譬如飛機、煉油廠、核子反應
爐等,雜訊是設計控制系統的重要考慮因素。一
個良好的工程設計,必須將量測誤差的問題列入
考慮,以免這些雜訊導致系統的不穩定行為(不
得有飛機失事、煉油廠爆炸或是核子反應爐熔化
的狀況發生!)。

第6章 使用者定義函式 第319頁


範例6.4 亂數產生器
大部分的工程設計會在建造系統之前,先以數值
模擬去測試系統的運作情形。這些模擬包括了建
立系統行為的數學模型,並輸入一些實際的資料
測試這些數學模型。如果數學模型對輸入資料的
反應正確,我們才能有合理的自信,實際系統也
會對真實的輸入資料產生同樣的正確反應。

第6章 使用者定義函式 第319頁


範例6.4 亂數產生器
為了模擬真實系統,提供給模型的輸入資料必須
含有量測雜訊,模擬雜訊的輸入資料只是在理想
的輸入資料加上一組亂數。這種模擬的量測雜訊
通常是由亂數產生器所產生的。

第6章 使用者定義函式 第319頁


範例6.4 亂數產生器
亂數產生器是每次呼叫時都會傳回不同且明顯為
亂數值的函式。事實上,這些亂數是從某既定的
演算法所計算而來,它們只是看起來像是隨機出
現而已。然而,只要產生亂數的演算法夠複雜,
對模擬的應用而言,這些數字就能算是隨機出現
的亂數了。

第6章 使用者定義函式 第319頁


範例6.4 亂數產生器
以下提供一個簡單的亂數產生器演算法的說明。
這是藉由模數函式處理大數字時所引起的不可預
測性來產生亂數。在第四章學過的模數函式mod
會傳回兩個整數相除的餘數。考慮下面的方程式

ni + 1 = mod(8121 ni + 28,411, 134,456) (6-6)

第6章 使用者定義函式 第319頁


6.4 使用全域記憶體分享資料
假設ni是一個非負值整數,因為模數函式的關係
,ni + 1將會是一個介於0至134,455之間的數字。接
下來,ni + 1可以輸入到方程式裡,產生也是介於0
至134,455的數字ni + 2。這個過程可以一直重複下
去,以產生一連串介於 [0, 134455] 範圍內的數字
。如果我們事先不知道8121、28,411以及134,456
這些數字,我們便不可能去猜出n值產生的順序。
此外,每個產生的亂數出現在序列的機率是相等
的(或是均勻分布)。因為這些性質,(6-6)式
可當作一個產生均勻分布亂數的簡易基本演算法
則。

第6章 使用者定義函式 第319-320頁


6.4 使用全域記憶體分享資料
我們現在將使用(6-6)式來設計一個亂數產生器
,以輸出在 [0.0, 1.0) 範圍的實數。

第6章 使用者定義函式 第320頁


範例6.4 亂數產生器-解
我們將編寫一個函式,每次呼叫都會產生一個在
0 ≤ ran < 1.0範圍的亂數。這個亂數將由下列方程
式產生:

ni
rani  (6-7)
134456

其中,ni是由(6-6)式所產生介於0到134,455間
的數字。

第6章 使用者定義函式 第320頁


範例6.4 亂數產生器-解
這個由(6-6)與(6-7)式所產生的數列與初始
值n0(稱為種子)的設定有很大的關係。我們必
須提供使用者一個設定n0的方法,使得每次執行
程式時,都會產生不同的數列。

第6章 使用者定義函式 第320頁


範例6.4 亂數產生器-解
1. 敘述問題。
 根據(6-6)與(6-7)式編寫一個random0函式,以產
生並傳回陣列ran,其包含一個或多個均勻分布亂數,
而且0 ≤ ran < 1.0。這個函式必須有一個或兩個輸入引
數(m和n),用以設定傳回的陣列大小。如果只有一
個輸入引數m,函式會產生一個大小為m×m的方形陣列
;如果有兩個輸入引數,函式會產生一個大小為m×n的
陣列。亂數種子的初始值n0將由呼叫函式seed來指定

第6章 使用者定義函式 第320頁


範例6.4 亂數產生器-解
2. 定義輸入和輸出。
 這個問題中有兩個函式:seed和random0。輸入到
seed函式的是一個整數,用做亂數序列的初始值,此
函式不需要輸出。 輸入到random0函式的是一個或兩
個整數,用來指定所產生亂數陣列的大小。假設只提
供一個引數m,函式會產生大小為m×m的方形陣列;假
設提供了兩個引數m與n,則函式會產生大小為m×n的陣
列。random0函式的輸出為一個陣列,其元素值為介
於 [0.0, 1.0) 範圍內的亂數。

第6章 使用者定義函式 第320-321頁


範例6.4 亂數產生器-解
3. 設計演算法。
 random0函式的虛擬碼如下:

function ran = random0(m, n)


檢查引數是否有效
假如沒有輸入n,設定 n ← m
使用"zeros"函式輸出陣列
for ii = 1:列數
for jj = 1:行數
ISEED ← mod(8121 * ISEED + 28411, 134456)
ran(ii,jj) ← ISEED / 134456
end
end

第6章 使用者定義函式 第321頁


範例6.4 亂數產生器-解
 其中ISEED為一全域變數,其數值被存放在全域記憶
體中。而seed函式的虛擬碼可簡單描述如下:
function seed(new_seed)
new_seed ← round(new_seed)
ISEED ← abs(new_seed)
 使用round函式是為了避免使用者輸入一個非整數,
而使用絕對值函數是為了避免使用者輸入一個負數。
使用者事先並不需要知道只有正整數才是合法的亂數
種子。
 全域變數ISEED將被存放在全域記憶體中,也因此它
能被這兩個函式所存取。

第6章 使用者定義函式 第321頁


範例6.4 亂數產生器-解
4. 把演算法變成MATLAB 敘述式。
 random0函式顯示如下:

function ran = random0(m,n)


%RANDOM0 Generate uniform random numbers in [0,1)
% Function RANDOM0 generates an array of uniform
% random numbers in the range [0,1). The usage
% is:
%
% random0(m) -- Generate an m x m array
% random0(m,n) -- Generate an m x n array

第6章 使用者定義函式 第321-322頁


範例6.4 亂數產生器-解
% Define variables:
% ii -- Index variable
% ISEED -- Random number seed (global)
% jj -- Index variable
% m -- Number of columns
% msg -- Error message
% n -- Number of rows
% ran -- Output array
%
% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/04/10 S. J. Chapman Original code

第6章 使用者定義函式 第322頁


範例6.4 亂數產生器-解
% Declare global values
global ISEED % Seed for random number generator

% Check for a legal number of input arguments.


msg = nargchk(1,2,nargin);
error(msg);

% If the n argument is missing, set it to m.


if nargin < 2
n = m;
end

第6章 使用者定義函式 第322頁


範例6.4 亂數產生器-解
% Initialize the output array
ran = zeros(m,n);

% Now calculate random values


for ii = 1:m
for jj = 1:n
ISEED = mod(8121*ISEED + 28411, 134456 );
ran(ii,jj) = ISEED / 134456;
end
end

第6章 使用者定義函式 第322頁


範例6.4 亂數產生器-解
 seed函式顯示如下列。

function seed(new_seed)
%SEED Set new seed for function random0
% Function SEED sets a new seed for function
% random0. The new seed should be a positive
% integer.

% Define variables:
% ISEED -- Random number seed (global)
% new_seed -- New seed

第6章 使用者定義函式 第322-323頁


範例6.4 亂數產生器-解
% Record of revisions:
% Date Programmer Description of change
% ==== ========== =====================
% 02/04/10 S. J. Chapman Original code
%
% Declare globl values
global ISEED % Seed for random number generator

% Check for a legal number of input arguments.


msg = nargchk(1,1,nargin);
error(msg);

% Save seed
new_seed = round(new_seed);
ISEED = abs(new_seed);
第6章 使用者定義函式 第323頁
範例6.4 亂數產生器-解

1
12

第6章 使用者定義函式 第323頁


範例6.4 亂數產生器-解
 此外,我們如果在介於0和1的範圍內劃分成幾個相同
大小的區間,則落入這些區間的亂數個數應大致相同
。直方圖(histogram)可用來畫出這些區間的亂數
個數。MATLAB的hist函式從輸入資料中產生並畫出
一張直方圖。我們將使用這個直方圖來驗證random0
函式所產生的亂數分布(如圖6.5)。

第6章 使用者定義函式 第323頁


範例6.4 亂數產生器-解
 為了測試這些函式的結果,我們將執行以下的測試條
件:
• (a) 呼叫seed函式,並設定new_seed為1024。
• (b) 呼叫random0(4)函式以查看輸出是否為隨機。
• (c) 呼叫random0(4)函式以確定每次的結果都不一樣。
• (d) 再次呼叫seed函式,並設定new_seed為1024。
• (e) 呼叫random0(4)以查看結果是否與條件2的結果相
同。這是為了驗證seed函式是否被正確地重新設定。
• (f) 呼叫random0(2,3)以驗證兩個輸入引數是否被正確
地使用。
• (g) 呼叫random0(1,100000)並使用MATLAB函式
mean和std來計算產生資料的平均值及標準差。比較這
1
些結果是否接近0.5及 12 。
第6章 使用者定義函式 第323-324頁
範例6.4 亂數產生器-解
• (h) 從條件7所得的資料,產生一張直方圖,以驗證在每
個區間是否落下大約相等數目的亂數。
 我們將執行這些測試,以確認我們之前所預期的結果

» seed(1024)
» random0(4)
ans =
0.0598 1.0000 0.0905 0.2060
0.2620 0.6432 0.6325 0.8392
0.6278 0.5463 0.7551 0.4554
0.3177 0.9105 0.1289 0.6230

第6章 使用者定義函式 第324頁


範例6.4 亂數產生器-解
» random0(4)
ans =
0.2266 0.3858 0.5876 0.7880
0.8415 0.9287 0.9855 0.1314
0.0982 0.6585 0.0543 0.4256
0.2387 0.7153 0.2606 0.8922
» seed(1024)
» random0(4)
ans =
0.0598 1.0000 0.0905 0.2060
0.2620 0.6432 0.6325 0.8392
0.6278 0.5463 0.7551 0.4554
0.3177 0.9105 0.1289 0.6230

第6章 使用者定義函式 第324頁


範例6.4 亂數產生器-解
» random0(2,3)
ans =
0.2266 0.3858 0.5876
0.7880 0.8415 0.9287
» arr = random0(1,100000);
» mean(arr)
ans =
0.5001
» std(arr)
ans =
0.2887

第6章 使用者定義函式 第324頁


範例6.4 亂數產生器-解

» hist(arr,10)
» title('\bfHistogram of the Output of random0');
» xlabel('Bin');
» ylabel('Count');

第6章 使用者定義函式 第324頁


範例6.4 亂數產生器-解
 測試結果看起來相當合理,所以函式似乎可以正常工
作。這些亂數資料的平均值為0.5001,與理論值的
0.5000非常接近,而亂數資料的標準差為0.2887,與理
論值一致。圖6.5的直方圖顯示了亂數值也概略地平均
分布在各個區間內。

第6章 使用者定義函式 第325頁


範例6.4 亂數產生器-解

第6章 使用者定義函式 第325頁

You might also like