Jiing’s Blog

Just another WordPress.com weblog

精通Matlab 6 第十六章 中譯

第十六章 矩陣代數(MATRIX ALGEBRA)

原本寫MATLAB是為了提供易用的介面給專業發展的數值線性代數子程序。當它演化了數年之後,其它的特性如圖形和圖形使用者介面已經使數值線性代數程序不再那麼的突出了。然而,MATLAB提供範泛的數值矩陣函式。

很重要的是要去注意到雖然MATLAB支援n維陣列,矩陣代數只定義在二維陣列上,也就是,向量和矩陣。

16.1 線性方程式的集合(SETS OF LINEAR EQUATIONS)

最常見的線性代數問題是解決線性組合的方程式。例如,考慮此方程式集合

其中數學乘法符號(.)現在定義在矩陣中的意義相對於之前討論過的陣列意義。在MATLAB中,矩陣乘法以星號(*)代表。上述方程式矩陣A和向量x的乘積等於向量y。上述方程式中解的存在性是線性代數的基本問題。再者,當解確實存在時,有許多方法可以找出解,例如高斯消去法(Gaussian elimination),LU分解法(LU factorization),或直接使用A-1。很清楚的,本節內容範圍專注於討論許多分析的和數值的矩陣代數。我們只希望證明如何用MATLAB來解決諸如上述的問題。
要解決上述的問題,你需要鍵入A和y:

>> A=[1 2 3;4 5 6
7 8 0]
A =
1 2 3
4 5 6
7 8 0
>> y=[366;804;351]
y =
366
804
351

和之前討論過的一樣,可以二種方式來輸入矩陣A,來讓MATLAB能分辨不同的列。介在和4之間的分號代表一新列的開始,和介於與7間的新行一樣。向量y是一行向量,因為每個分號代表一新列的開始。
若你具有線性代數的底子,很容易可證明此問題有唯一解,只要A的秩(rank)和引數矩陣的秩都等於3即可。另一個方法是,你可以檢查A的condition number。如果condition number不過大,那麼A有一個具有良好數值性質的反矩陣。測試此問題可產生如下的結果

>> rank(A)
ans =
3
>> rank([A y])
ans =
3
>> cond(A)
ans =
35.1059

因為秩和condition number的測試結果均成立,MATLAB可以二種方法來找出 的解,其中有一個較受人喜愛。另一個較不受人喜愛,但卻更加直觀的方法是就字面上令 。例如,

>> x=inv(A)*y
x =
25.0000
22.0000
99.0000

此處inv(A)是計算A-1的MATLAB函式,而乘法運算子*是矩陣乘法。較受人喜愛的解要藉由使用矩陣左除法運算子或右斜線(backward slash)來求得,例如

>> x=Ay
x =
25.0000
22.0000
99.0000

此方程式利用LU分解(LU factorization)法,並且將結果表示為A左除於y。左除法運算子之前並沒有點(.),因此為矩陣運算,而非逐一元素的陣列運算。為何第二個方法較愛喜愛的理由有許多個。其中最簡單的就是第二個方法需要較少的浮點運算,因此解題的速度快得多。此外,這個解一般也更精確,尤其對大型問題時。無論任何一個方法,如果MATLAB不能找到解或不能精確地找出解時,它會顯示警告訊息。
如果上述線性方程組被轉置,也就是, ,那麼上述的線性方程組可被寫成 ,其中 和 是列量向。結果是,它同樣能有效地藉由列向量和矩陣的乘積等於另一個列向量來表示線性方程組,例如,u.B = v。在MATLAB裡,此例也能藉由同樣的演算法使用矩陣右除法運算子或左斜線(forward slash)如u=v/B來求解。

很重要的是要注意到當MATLAB遇到左斜線(forward slash)或右斜線(backward slash)時,它會檢查係數矩陣的結構以決定要使用哪個內部演算法來求解。特別是當矩陣是上或下三角矩陣或是上或下三角矩陣的排列時,MATLAB並不會再次分解矩陣,而是就只執行所需要的左斜線(forward slash)或右斜線(backward slash)取代步驟來求解。結論是,MATLAB使用係數矩陣的特性來儘快地計算求解。
如果你已有穩固的線性代數的底子,你會知道當方程式和未知數的數目不相等時,通常不存在唯一解。然而,若加入更多的限制式,通常可以找到有實用性的解。在MATLAB中,當rank(A)=min(r,c),其中r和c分別是A的列數和行數,且方程式的數目多於未知數的數目(r>c),也就是,無解的情況(overdetermined case),此時會使用除法運算子或/來找出最小化平方殘差(squared residual)或稱平方差e = A.x -y的norm的解。此解很具實用價值且被稱為最小平方解(least squares solution)。考慮下例。

>> A=[1 2 3;4 5 6;7 8 0;2 5 8]
A =
1 2 3
4 5 6
7 8 0
2 5 8

>> y=[366 804 351 514]&#039
y =
366
804
351
514
>> x=Ay
x =
247.9818
-173.1091
114.9273
>> e=A*x-y
e =
-119.4545
11.9455
0.0000
35.8364
>> norm(e)
ans =
125.2850

除了以左、右除法運算子計算出最小平方法的解外,MATLAB也提供函式lscov及lsqnonneg。函式lsconv是當資料的共變異(covariance)矩陣已知時,用來解決有權重的最小平方問題,而lsqnonneg找出非負最小平方解,其中所有的解都被限制要是正的。

當方程式數小於未知數時(r<c),也就是多重解的(underdetermined)狀況,會有無限多個解存在。MATLAB以二種直觀的方式來計算這些解。第一種是使用除法運算子來求出x元素中有最多個0的解。另一個方法就是計算x=pinv(A)*y來求出具有最小norm的長度的解。根據pseudoinverse,此解也有很大的實用價值,且被稱作最小norm解(minimum norm solution)。例如,<br />

>> A=A&#039 % 建立三條方程式,裡面有4個未知數
A =
1 4 7 2
2 5 8 5
3 6 0 8
>> b=y(1:3) % 新的右手邊(r.h.s)變數(此處原書有筆誤)
b =
366
804
351
>> x=A
x =
0
-165.9000
99.0000
168.3000
>> xn=pinv(A)*y % 最小norm的解
xn =
30.8182
-168.9818
99.0000
159.0545
>> norm(x) % 有最多0的解的norm
ans =
256.2200
>> norm(xn) % 最小norm解確實有最小的norm!
ans =
254.1731

16.2 矩陣函式(MATRIX FUNCTIONS)

除了線性方程組的解外,MATLAB提供了數個在解決數值線性代數問題時很有用的矩陣函式。若要對這些函式作透徹地討論,則會超出了本書的範圍。一般,MATLAB提供了所有常見的和一些不常見的數值線性代數問題的函式。下表中是對於其中一些矩陣函式的簡短描述。

函式 描述
A^n 取冪,例如,A^3=A*A*A
balance(A) 按比例放大或縮小以增進特徵值(eigenvalue)的精確度
[V,D]=cdf2rdf(V,D) 將complex diagonal form轉換為real block diagonal form
chol(A) Cholesky 分解(Cholesky factorization)
cond(A) 矩陣的條件數(condition number)
condest(A) 1-norm的條件數(condition number)估計
[V,D,S]=condeig(A) 與重複特徵值相關的條件數(condition number)
det(A) 行列式
eig(A) 特徵值的向量
[V,d]=eig(A) 特徵向量的矩陣,和包含特徵值的對角矩陣
expm(A) 矩陣指數(exponential)
funm(A) 泛用矩陣函式
gsvd(A) 一般化的奇異值(singular value)
[U,V,X,C,S]=gsvd(A) 一般化的奇異值分解。
hess(A) 矩陣的Hessenburg型
inv(A) 反矩陣
logm(A) 對矩陣取對數
lscon(A,y,V) 共變異矩陣的最小平方解
lsqnonnet(A,y) 非負的最小平方解
[L,U]=lu(A) LU分解
minres(A,y) 最小殘差法(Minimum residual method)
norm(A,type) 取矩陣和向量的norm
null(A) Null空間
orth(A) Orthogonal range space
pinv(A) Pseudoinverse
poly(A) 特徵多項式
polyeig(A0,A1,…) 多項式的特徵值解
polyvalm(A) 評估矩陣多項式
qr(A) Orthogonal-triangular 分解
qz(A,B) 一般化的特徵值
rank(A) 矩陣的秩
rcond(A) LAPACK reciprocal condition estimator
rref(A) 列簡化梯矩陣(Reduced row echelon form)
rsf2csf(A) 將real Schur form轉換為complex Schur form
schur(A) Schur分解
subspace(A,B) 介於二個子空間之間的角度
svd(A) 奇異值(singular value)
[U,S,V]=svd(A) 奇異值分解
symmlq(A,y) 對稱的LQ解法
trace(A) A的跡(trace)

16.3 特殊的矩陣(SPECIAL MATRICES)

MATLAB提供了一些特殊的矩陣;當中有一些是一般用途的,不過其它的矩陣則是與特定學科相關。這些和其它特殊的矩陣包含在下表中的那些。請使用線上輔助說明來學習更多關於這些矩陣的知識。

矩陣 描述
[] 空矩陣
blkdiag(a0,a1,…) 對輸入引數作區塊的對角連結
company(P) 多項式的伴隨矩陣(companion matrix)
eye(r,c) 單位矩陣
gallery 超過50個測試的矩陣
hadamard(n) order為n的Hadamard矩陣
Hankel(C) Hankel 矩陣
hilb(n) order為n的Hilbert矩陣
invhilb(n) order為n的反Hilbert矩陣
magic(n) order為n的魔術方陣
ones(r,c) 裡面包含的元素全是1的矩陣
pascal(n) order為n的巴斯卡矩陣
rand(r,c) 均勻分配的隨機矩陣,其中元素介於0和1
randn(r,c) 常態分配的隨機矩陣,其中元素的平均值為0,變異數為1
rosser 古典對稱的特徵值測試問題
toeplitz(C,R) Toeplitz矩陣
vander(C) Vandermonde矩陣
wilkinson(n) order為n的Wilkinson的特徵值測試矩陣
zeros(r,c) 裡面包含的元素全是0的矩陣

16.4 稀疏矩陣(SPARSE MATRICES)

在許多實際應用中,會產生只有包含少數幾個非零元素的矩陣。結果,這些矩陣被稱作是稀疏的(sparse)。例如,電路模擬和有限元素分析程式老是在處理那種包含少於1% 非零元素的矩陣。如果矩陣很大時,例如,max(size(A))>100,並且元素為零的比率很高,它既浪費電腦的記憶體去儲存那些非零元素,也浪費運算能力去拿為零的元素來執行算術運算。要消除零元素的儲存空間,一般是只儲存稀疏矩陣的非零元素和用來指出這些元素的列和行位置的二組索引。類似地,要消除在為零元素上的算術運算,必須發展特殊的演算法來解決典型的矩陣問題,譬如解一組線性方程組,其中包含零的運算被減至最少且暫時中介性的矩陣也要有最少的非零元素。

用來最佳化稀疏矩陣運算的技巧在實作上和理論上都十分地複雜。幸運的是,MATLAB將其複雜度隱藏了。在MATLAB中,稀疏矩陣被儲在變數中就如一般的填得滿滿的(full)矩陣一樣。再者,大多數稀疏矩陣的運算和在填得滿滿的矩陣中用的是相同的語法。特別是,所有MATLAB的陣列處理能力在稀疏矩陣上也能運作地一樣好。例如,s(i,j)=value會將非零元素增加到稀疏矩陣s的第i列、第j行。

在本書中,只有舉例說明稀疏矩陣的建立法和如何在稀疏矩陣與一般矩陣間作轉換。一般來說,在full矩陣上的運算會產生full矩陣,而在稀疏矩陣上的運算會產生稀疏矩陣。此外,在稀疏和full混合矩陣上的運算一般會產生稀疏矩陣,除非運算的結果有太緊密(dense)的非零元素,為了有效率地儲存使然。

使用MATLAB函式sparse可建立稀疏矩陣。例如,

>> As = sparse(1:10,1:10,ones(1,10))
As =
(1,1) 1
(2,2) 1
(3,3) 1
(4,4) 1
(5,5) 1
(6,6) 1
(7,7) 1
(8,8) 1
(9,9) 1
(10,10) 1

建立了一個10-by-10的單位矩陣。sparse(i,j,s)的用法會建立一個稀疏矩陣,其中它的第k個非零元素是s(k),而s(k)出現在第i(k)列和第j(k)行。非零元素及它們的列和行的位置都被顯示了。上面的稀疏矩陣也可以轉換的方式來建立。例如,

>> As=sparse(eye(10))
As =
(1,1) 1
(2,2) 1
(3,3) 1
(4,4) 1
(5,5) 1
(6,6) 1
(7,7) 1
(8,8) 1
(9,9) 1
(10,10) 1

建立了一個10-by-10的單位矩陣。這次是利用將full矩陣eye(10)轉換為稀疏型。雖然這個方法也能建立稀疏矩陣,實際上它很少被使用,因為初始的full矩陣浪費了大量的記憶體。

在給定稀疏矩陣的情況下,函式full會產生等價的full矩陣轉換。例如,

>> A=full(As)
A =
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1

將稀疏矩陣As轉換回它的full型。

對於稀疏矩陣是如何儲存在full矩陣中,請考慮下例。

>> B=eye(200);
>> Bs=sparse(B);
>> whos
Name Size Bytes Class

B 200×200 320000 double array
Bs 200×200 3204 sparse array

Grand total is 40200 elements using 323204 bytes

在此稀疏矩陣Bs包含只有.%的非零元素且需要3204bytes的記憶體。另一方面,B,同樣的full矩陣型則需要近100倍多的記憶體!

16.5 稀疏矩陣相關函式(SPARSE MATRIX FUNCTIONS)

MATLAB提供許多的稀疏矩陣函式。其中有許多個包含各方面和各種用來解稀疏矩陣聯立方程式的技巧。討論這些函式超過了本書的範圍。在此,我們將可用的函式列於下表。

稀疏矩陣相關函式 描述
bic Biconjugagte gradient interative linear equation solution(雙共軛梯度反覆線性方程解?)
bicstab Biconjugagte gradient stabilized interative linear equation solution(雙共軛梯度穩定反覆線性方程解?)
cgs Conjugagte gradients squared interative linear equation solution(共軛梯度平方反覆線性方程解?)
cholinc 不完全Cholesky 分解(incomplete Cholesky factorization)
colamd Column approximate minimum degree reordering method.(行近似最小degree重新排序法)
colamdtree Colamd followed column elimination tree postordering.(遵循行消去樹後序法的colamd)
colmmd Column minimum degree reordering method(行最小degree重新排序法)
colperm 行排列
condest 1-norm condition number estimate.(1-norm 條件數的估計)
dmperm Dulmage-Mendelsohn reordering method.(Dulmage-Mendelsohn重新排序法)
egis 使用ARPACK找出的一些特徵值
etree 消去樹
etreeplot 繪製出消去樹的圖
find 找出非零元素的索引
full 將稀疏矩陣轉換為full矩陣
gmres Generalized minimum residual iterative linear equation solution.(一般化的最小殘差反覆線性方程解)
gplot 建構圖論的圖形
issparse 若為稀疏矩陣,則為True;若否,則為False。
lsqr LSQR implementation on conjugate gradients on normal equations.(在正規方程式上的共軛梯度的LSQR實作)
luinc 實作LU分解
minres Minimum residual iterative linear equation solution.(最小殘差反覆線性方程解)
nnz 非零矩陣元素的個數
nonzeros 非零矩陣元素
normest 矩陣2-norm的估計值
nzmax 配置給非零元素的儲存空間
pcg Preconditioned conjugate gradients iterative linear equation solution.(預設條件的共軛反覆線性方程解)
qmr Quasi-minimal residual iterative linear equation solution.(似最小化殘差反覆線性方程解)
randperm 隨機排列
spalloc 配置空間給稀疏矩陣
sparse 建立稀疏矩陣
spaugment 形成最小平方引數系統
spconvert 從稀疏矩陣外部格式匯入
spdiags 由對角線形成稀疏矩陣
speye 稀疏單位矩陣
spfun 套用函式到非零元素上
spones 取代非零值為1
spparms 設定參數給稀疏矩陣例行程序
sprand 稀疏均勻分配矩陣
sprandn 稀疏常態分配矩陣
sprandsym 稀疏隨機對稱矩陣
sprank 結構的秩
spy 視覺化稀疏的樣型
svds 一些奇異值(singular value)
symbfact 符號分解分析
symamd 對稱近似最小degree重新排序法
symamdtree 遵循對稱的消去樹後序法的symamd
symmd 對稱的最小degree重新排序法
symmlq 對稱LQ反覆線性方程式解
symrcm 對稱反Cuthill-Mckee重新排序法
treelayout 陳列展開樹或森林
treeplot 畫出樹狀圖

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第十五章 中譯

第十五章 時間的計算(Time Computations)

MATLAB提供了許多的函式來處理時間。你可以執行日期和時間算術運算、列印出月曆並且找出指定的日期。MATLAB可以這麼做,因為它利用將日期和時間儲存為雙精度數值來表示自從西元0年起的天數。例如,2000年一月一日的半夜被表示為730486,而同一天的中年是730486.5。此格式可讓電腦計算變得更容易,不過它很難以想像來解釋。這就是為什麼MATLAB支援許多的函式來進行介於日期數和字元字串間的轉換及處理日期和時間。

15.1 現在的日期和時間(CURRENT DATE AND TIME)

函式clock會傳回現在的日期和時間於陣列中,例如,

>> T=clock
T =

2000 6 27 15 37 47.04

這是當這部份的文字被撰寫的時間。上面的資料被組織為T = [year month day hour minute seconds]。所以上面的時間是西元2000年,第六個月,第27天,第15個小時,第37分,第47.04秒。
函式now會以雙精度日期數或簡單的一個日期數字來傳回目前的日期和時間。

>> format long
>> t=now
t =
7.306646527226851e+005
>> format short g

T和t基本上表示了相同的資訊。
函式date會用字元字串以dd-mmm-yyyy的格式來傳回現在的時間。

>> date
ans =
27-Jun-2000

15.2 日期的格式轉換(DATE FORMAT CONVERSIONS)

一般來說,有時間的數學包括轉換時間為日期數的格式,在時間上執行標準數學運算,然後轉換結果回去成一種讓人看得懂的格式。結論是,在不同的格式間轉換時間是非常重要的。MATLAB提供三種格式給日期:(1)雙精度日期數,(2)各種風格的日期(字元)字串,和(3)數值的日期向量,其中每個元數包含了一個不同的日期元件,也就是,[year month day hour minute seconds]。
函式datestr會將日期數字轉換為日期字串。datestr的使用語法是datestr(date,dateform),其中dateform由datestr的輔助說明文字來加以描述:

>> help datestr
DATESTR String representation of date.
DATESTR(D,DATEFORM) converts a serial data number D (as returned by
DATENUM) or a free format date string into a date string with a
format specified by format number or string DATEFORM (see table below).
By default, DATEFORM is 1, 16, or 0 depending on whether D contains
dates, times or both. Date strings with 2 character years are interpreted
to be within the 100 years centered around the current year.

DATESTR(D,DATEFORM,PIVOTYEAR) uses the specified pivot year as the
starting year of the 100-year range in which a two-character year
resides. The default pivot year is the current year minus 50 years.
DATEFORM = -1 uses the default format.

DATEFORM number DATEFORM string Example
0 &#039dd-mmm-yyyy HH:MM:SS&#039 01-Mar-2000 15:45:17
1 &#039dd-mmm-yyyy&#039 01-Mar-2000
2 &#039mm/dd/yy&#039 03/01/00
3 &#039mmm&#039 Mar
4 &#039m&#039 M
5 &#039mm&#039 03
6 &#039mm/dd&#039 03/01
7 &#039dd&#039 01
8 &#039ddd&#039 Wed
9 &#039d&#039 W
10 &#039yyyy&#039 2000
11 &#039yy&#039 00
12 &#039mmmyy&#039 Mar00
13 &#039HH:MM:SS&#039 15:45:17
14 &#039HH:MM:SS PM&#039 3:45:17 PM
15 &#039HH:MM&#039 15:45
16 &#039HH:MM PM&#039 3:45 PM
17 &#039QQ-YY&#039 Q1-96
18 &#039QQ&#039 Q1
19 &#039dd/mm&#039 01/03
20 &#039dd/mm/yy&#039 01/03/00
21 &#039mmm.dd,yyyy HH:MM:SS&#039 Mar.01,2000 15:45:17
22 &#039mmm.dd,yyyy&#039 Mar.01,2000
23 &#039mm/dd/yyyy&#039 03/01/2000
24 &#039dd/mm/yyyy&#039 01/03/2000
25 &#039yy/mm/dd&#039 00/03/01
26 &#039yyyy/mm/dd&#039 2000/03/01
27 &#039QQ-YYYY&#039 Q1-1996
28 &#039mmmyyyy&#039 Mar2000

See also DATE, DATENUM, DATEVEC, DATETICK.

以下是一些datestr用法的範例

>> t=now
t =
7.3066e+005
>> datestr(t)
ans =
27-Jun-2000 16:22:56
>> class(ans)
ans =
char

>> datestr(t,12)
ans =
Jun00
>> datestr(t,23)
ans =
6/27/2000
>> datestr(t,24)
ans =
27/06/2000
>> datestr(t,25)
ans =
00/06/27
>> datestr(t,13)
ans =
16:22:56

函式datenum是datestr的反函式。也就是,datenum使用datenum(str)的型式來將日期字串轉換為日期數。另外,它也仗用datenum(year,month,dat)或datenum(year,month,day,hour,minute,second)的型式來轉換個別的日期規格。考慮下例

>> t=now
t =
7.306647000825232+005
>> ts=datestr(t)
ts =
27-Jun-2000 16:48:07
>> datenum(ts)
ans =
7.306647000810185e+005
>> datenum(2000,6,27,16,48,07)
ans =
7.306647000810185e+005
>> datenum(2000,6,27)
ans =
730664

函式datevec使用datestr的格式0,,2,,13,14,15或16來將日期字串轉換為包含日期元件的數值向量。另外,它也將日期數轉換為日期元件的數值向量,例如,

>> [yr,mo,dat,hr,min,sec]=datevec(པ-Dec-1984 08:22&#039)
yr =
1984
mo =
12
dat =
24
hr =
8
min =
21
sec =
60

15.3 日期函式(DATE FUNCTIONS)

使用函式weekday可以從日期字串或日期數中找出每週的數值天數。MATLAB使用星期日為第1天而星期六為第7天的轉換方法,例如,

>> [d,w]=weekday(728647)
d =
2
w =
Mon
>> [d,w]=weekday(ད-Dec-1994&#039)
d =
4
w =
Wed

使用函式eomday可找到任何月份的最後一天。因為有閏年(leap year)的關係,所以年和月都需要,例如,

>> eomday(1996,2) % 可被4整除,是閏年
ans =
29
>> eomday(1900,2) % 可被100整除,不是閏年
ans =
28
>> eomday(2000,2) % 可被400整除,是閏年
ans =
29

使用函式calendar,MATLAB可產生你所需的任何月份的月曆並且在Command window中顯示它或是將它放在6-by-7的矩陣中,例如,

>> calendar(date)
Jun 2000
S M Tu W Th F S
0 0 0 0 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 0
0 0 0 0 0 0 0
>> calendar(2000,6)
Jun 2000
S M Tu W Th F S
0 0 0 0 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 0
0 0 0 0 0 0 0
>> x=calendar(2000,6)
x =
0 0 0 0 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 0
0 0 0 0 0 0 0
>> class(x)
ans =
double

15.4 計時函式(TIMING FUNCTIONS)

函式tic和toc被用來計算一連串MATLAB作業的時間。Tic啟動碼表;toc停止碼表並顯示所耗費的時間:

>> tic;plot(rand(50,5));toc
elapsed_time =
0.33
>> tic;plot(rand(50,5));toc
elapsed_time =
0. 11

注意到個別plot命令中所耗費時間的差別。第二個plot快得多了,因為MATLAB已經建立了Figure window 且編譯了函式(如果有需要的話)並放置到記憶體中了。
函式cputime以秒傳回自從目前session開始到現在為止,使用MATLAB的「中央處理器(CPU)時間」的數目。函式etime計算介於以六個元素的型式的二個時間向量(如由函式clock和datevec傳回的向量)所耗費的時間。cputime和etime都可以被用來計算它用來使一作業被完成所花費的時間。事實上,函式tic和toc只是自動使用clock和etime去計算耗費的時間。Cputime和etime的用法可以下例說明,其中myoperation是一個包含一些MATLAB命令的script檔。

>> t0=cputime;myoperation;cputime-t0
and=
0.149999999999991
>> t1=cputime;myoperation;etime(cputime-t1)
and=
11.284853

15.5 繪圖標示(PLOT LABELS)

有時候繪製資料並在一或多個座標軸標籤上使用日期或時間字串會很有用。函式datetick將此項工作自動化了。使用此函式需要「被標示的軸及要繪製的日期數的向量」要,例如,函式datenum的輸出。

>> t=(1900:10:1990)&#039
>> p=[75.995; 91.972; 105.771; 123.203; 131.669;
150.697; 179.323; 203.212; 226.505; 249.633];
>> plot(datenum(t,1,1),p)
>> datetick(&#039x&#039,&#039yyyy&#039) % 在x軸上使用4位數的年份
>> title(&#039Figure 15.1: Population by Year&#039)

在此我們建立了一個從1998年11月到1999年12月間公司銷售的長條圖:

>> y=[1998 1998 1999*ones(1,12)]&#039
>> m=[11 12 (1:12)]&#039
>> s=[1.1 1.3 1.2 1.4 1.6 1.5 1.7 1.6 1.8 1.3 1.9 1.7 1.6 1.95]&#039
>> bar(datenum(y,m,1),s)
>> datetick(&#039x&#039,&#039mmmyy&#039)
>> ylabel(&#039 $ Million&#039)
>> title(&#039Figure 15.2: Monthly Sales&#039)

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第十四章 中譯

第十四章 集合、位元和基底函式(Sets, Bit, and Base Functions)

14.1 集合函式(SET FUNCTIONS)
因為陣列是數值的有序集合,它們可以被想成是集合論中的集合(sets)。有了此項認知,MATLAB提供數個函式來測試和比較集合。最簡單的測試就是測試二集合是否相等,例如,

>> a=rand(2,5); % 隨機陣列
>> b=randn(2,5); % 一個不同的陣列
>> isequal(a,b) % a和b並不相等
ans =
0
>> isequal(a,a) % 不過a確實等於a
ans =
1
>> isequal(a,a(:)) % a和變成一行的a
ans =
0

若兩個陣列要相等,它們必須有相同的維度和相同的內容。此函式可套用到所有MATLAB的資料型別,不只是數值陣列,例如,

>> a=&#039a string&#039
>> b=&#039a String&#039
>> isequal(a,b) % 測試字元字串是否相等
ans =
0
>> isequal(a,a)
ans =
1
>> a={&#039one&#039 &#039two &#039 &#039three&#039};
>> b={&#039one&#039 &#039two &#039 &#039four&#039};
>> isequal(a,b) % 測試巢狀陣列是否相等
ans =
0
>> isequal(a,a)
ans =
1

>> a.one=&#039one&#039
>> a.two=2;
>> a.three=pi;
>> b.two=2;
>> b.one=&#039one&#039
>> b.three=pi;
>> isequal(a,b) % 測試結構是否相等
ans =
0
>> isequal(a,a)
ans =
1

如果MATLAB變數有相同的大小且恰有相同的內容,則它們是相等的。如果兩個結構有相同的大小、它們有相同的內容,且以相同的次序建立欄位,則它們是相同的。
函式unique從已知集合中移除重複項(item):

>> A=[2:2:8;4:2:10] % 新資料
A =
2 4 6 8
4 6 8 10

>> unique(A) %獨一無二的元素被存在一行裡
ans =
2
4
6
8
10

unique會傳回已排序好的行向量,因為在重複值移除後不可能去維持陣列的維度。Unique也套用到字串的巢狀陣列,例如,

>> c={&#039Shania&#039 &#039Britney&#039 &#039Dixie&#039 &#039Shania&#039 &#039Faith&#039};
>> unique(c)
ans =
&#039Britney&#039 &#039Dixie&#039 &#039Faith&#039 &#039Shania&#039

函式ismember可以決定是否為集合的成員,例如,

>> a=1:9
a =
1 2 3 4 5 6 7 8 9
>> b=2:2:9
b =
2 4 6 8
>> ismember(a,b) % a中有哪些元素在b中
ans =
0 1 0 1 0 1 0 1 0
>> ismember(b,a) % b中有哪些元素在a中
ans =
1 1 1 1

對於向量引數,ismember會傳回與第一個引數同樣大小的邏輯陣列,此陣列以1s出現在二個向量有共同值的索引處。

>> A=eye(3); % 新資料
>> B=ones(3);
>> ismember(A,B) % 在A中的這些元素是否也在B中
ans =
1 0 0
0 1 0
0 0 1
>> ismember(B,A)
ans =
1 1 1
1 1 1
1 1 1 [譯者註]此處與原書不同

對於二維陣列ismember傳回一行向量,當二個引數有共同值時,此行量向中的1s會出現在第一個引數的單索引(single index)處。函式ismember也可以套用到字串的巢狀陣列上,例如,

>> ismember(c,&#039Dixie&#039)
ans =
0 0 1 0 0

集合的算術運算可以由函式union, intersect, setdiff和setxor來加以達成。以下是使用這些函式的範例。

>> a,b % 回憶起資料
a =
1 2 3 4 5 6 7 8 9
b =
2 4 6 8
>> union(a,b) % a和b的聯集(union)
ans =
1 2 3 4 5 6 7 8 9
>> intersect(a,b) % a和b的交集(intersection)
ans =
2 4 6 8
>> setxor(a,b) % a和b的set exclusive or
ans =
1 3 5 7 9
>> setdiff(a,b) % a和b的差集,在a中的值不在b中的
ans =
1 3 5 7 9
>> setdiff(b,a) % b和a的差集,在b中的值不在a中的
ans =
[]
>> union(A,B) % 矩陣輸入產生排序彎的行陣列[此處實驗結果與原書不同]

??? Error using ==> union
A and B must be vectors or &#039rows&#039 must be specified.
>> A
A =

1 0 0
0 1 0
0 0 1
>> B
B =
1 1 1
1 1 1
1 1 1

像在本章之前討論過的函式一樣,這些集合函式也可套用到字串的巢狀陣列上。

14.2 位元函式(BIT FUNCTIONS)

除了在上一章討論過的邏輯運算子外,MATLAB提供了在浮點整數上的個別位元或的邏輯運算的函式。因為MATLAB將所有的數值表為雙精度浮點數(IEEE算術運算,IEEE arithmetic),整數也被表為叫作是flints的浮點整數。結論是,IEEE算術運算相容的電腦可以獨一無二地表示從0到 -1的範圍的整數。MATLAB逐一位元的函式bitand, bitcmp, bitor, bitxor, bitset, bitget和bitshift可在此範圍的整數上作用。
使用位元運算子可表示的最大整數是bitmax,在可執行IEEE算術運算的電腦上也就是 -1。

>> format hex % 將格式改為16進位
>> bitmax
ans =
433fffffffffffff

下面是位元運算的範例。

>> a=(2^24)-1 % 資料
a =
416fffffe0000000
>> b=123456789 % 資料
b =
419d6f3454000000
>> bitand(a,b) % (a & b)
ans =
4156f34540000000
>> bitor(a,b) % (a | b)
ans =
419ffffffc000000
>> bitxor(a,b) % xor(a,b)
ans =
419e90cba8000000
>> bitcmp(0,10)
ans =
408ff80000000000
>> bitget(a,1) % 取出a的第一個bit
ans =
3ff0000000000000
>> bitset(a,30) % 將的第30個bit設為1
ans =
41c07fffff800000
>> format short g % 重新設定顯示的格式

14.3 基底的轉換(BASE CONVERSIONS)

MATLAB提供許多的公用函式來以字元字串的型式,轉換十進位數為其它基底的數。藉由執行函式dec2bin和bin2dec可進行介於十進位和二元數值間的轉換,例如,

>> a = dec2bin(17) % 找出17的二元表示法
a =
10001
>> class(a) % 結果是一個字元字串
ans =
char
>> bin2dec(a) % 轉回去成十進位數
ans =
17
>> class(ans) % 結果是個雙精度的十進位數
ans =
double

藉由執行dec2hex和hex2dec可進行介於十進位與十六進位間的轉換,如下例

>> a=dec2hex(2047) % 2047的十六進位表示法
a =
7FF
>> class(a) % 結果是個字元字串
ans =
char
>> hex2dec(a) % 轉回去成十進位數
ans =
2047
>> class(ans) % 結果是個雙精度的十進位數
ans =
double

藉由執行dec2base和base2dec可進行介於十進位與「任何介於2與36間的基底」的轉換,例如,

>> a=dec2base(26,3)
a =
222
>> class(a)
ans =
char
>> base2dec(a,3)
ans =
26

基底36是最大可用的基底,因為它使用數字0到9和字母A到Z來表示基底為36數的36個不同的數值。

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 1 則迴響

精通Matlab 6 第十三章 中譯

第十三章 檔案和目錄管理(File and Directory Management)

MATLAB以各種檔案格式來開始及儲存資料檔,其中有些檔案格式是適合MATLAB的格式,其它的則是工業標準,還有一些其它的檔案格式適合其它的應用程式。被用來開啟和儲存資料檔的技術包含了GUI和Command window函式。
像大部份現代的應用程式,MATLAB使用目前的目錄當作是預設的資料和M-file的位置。利用GUI和Command window函式可以是目錄管理工具和改變目前的目錄。
本章涵蓋了MATLAB中檔案和目錄管理的特性。

13.1 原始資料檔(NATIVE DATA FILES)
藉由使用save 命令,MATLAB workspace中的變數可以以MATLAB原始格式來儲存。例如,

>> save

以MATLAB二元格式儲存所有在MATLAB workspace中的變數於目前目錄下的matlab.mat檔案中。這些原始二元MAT-files維持完整的雙精度就和變數被儲存的名稱一樣。MAT-file並非平台獨立的,不過卻是完全跨平台相容的(cross-platform-compatible)。被儲存在一平台上的變數可以不經特殊的處理就在其它MATLAB平台上被開啟。
Save命令也可以用來儲存特殊變數。例如,

>> save var1 var2 var3

只儲存變數var1, var2和var3到matlabmat中。檔案名稱可以被指定為save的第一個引數。例如,

>> save filename var1 var2 var3

儲存變數var1, var2和var3到filename.mat中。
使用命令-函數的對偶性,上述命令型式也可以被寫為函式型式如

>> save (&#039 filename&#039, &#039var1&#039, &#039var2&#039,&#039var3&#039)

此特別的格式在檔案名稱被儲存在MATLAB字元字串中時會很有用,例如,

>> fname=&#039myfile&#039
>> save (&#039 fname&#039, &#039var1&#039, &#039var2&#039,&#039var3&#039)

在此,有名稱的變數被儲存在名為myfile.mat的檔案中。

除了上述簡單的型式外,save命令也支援儲存到ASCII文字格式的選項,並且可被用來增加資料到目前已經存在的檔案中。若需這些特性的輔助說明,請參考線上輔助說明。

與save互補的就是load命令了。此命令開啟已由save命令建立的資料檔,或是與save命令相容的檔案。例如,

>> load

會讀取所有從matlab.mat中找到的變數,而無論從目前目錄下找到的或是在MATLAB搜尋路徑上找到的,此matlabmat檔是先找到的那一個。原本儲存在matlabmat中的變數名稱現在於workspace中還原了,且它們會覆寫在workspace中相似名稱的變數。
要從MAT-file中讀取特定變數,你必須包含檔案名稱和變數列表,例如,

>> load filename var1 var2 var3
>> load (&#039 filename&#039, &#039var1&#039, &#039var2&#039,&#039var3&#039)

在此filename.mat被開啟,而變數var1,var2和 var3被讀取到workspace中。第二個陳述式說明load命令的函式型可讓資料檔被指定為字元字串。雖然沒有顯示山來,filename字串可以包含完整的或部份的路徑,因此限制load去在特定的目錄尋找資料檔。
上面較後面的例子提供了一個開啟一連串以數字編號的資料檔的方法,例如mydata1.mat,mydata2.mat,等…,如下例

for i=1:N
fname=sprintf(&#039mydata%d&#039,i);
load(fname)
end

此程式碼片段使用sprintf來在For迴圈中建立檔案名稱字串,使得一連串的資料檔被讀取到workspace中。
當你不希望覆寫workspace中的變數時,load命令可以以函數型撰寫,並給定輸出引數。例如,

>> vnew=load(&#039filename&#039,&#039var1&#039,&#039var2&#039);

開啟檔案filenamemat並且讀取變數var1和var2到一個名為vnew,並具有欄位var1和var2的結構(structure)變數中。也就是,vnew.var1=var1且vnew.var2=var2。
load命令也可以開啟ASCII文字檔。特別是,如果由MATLAB的註解行和數列由空白字元分隔的數值所構成的資料檔,語法

>> load filename.ext

開啟檔案filename.ext並讀取資料到一個名為filename的單雙精度資料陣列。若需關於load命令更詳盡的資訊,請見線上輔助說明。
要找出是否資料檔中存在且它存有什麼變數,MATLAB命令exist和whos會很有用。例如,

>> exist(&#039matlab.mat&#039,&#039file&#039)

會傳回0如果file不存在,會傳回2如果它存在

>> whos -file matlab.mat

對於包含在檔案matlab.mat中的變數,會傳回標準whos於Command window的顯示。另一個方法,

>> w=whos(&#039-file&#039,&#039matlab.mat&#039)
w =
3×1 struct array with fields:
name
size
bytes
class

傳回有著「為了whos的顯示」而命名的欄位的結構陣列。使用此方式,變數的名稱,大小,記憶體和class都會被儲存在變數中。
最後,不過並非不重要,資料檔可以使用Command window命令delete來被刪除。例如,

>> delete filename.ext

會刪除名為filename.ext的檔案。
在MATLAB版本6中資料檔管理函式可被從Workspace space 瀏覽器中及輸入精靈(Import wizard)存取。藉由選擇在MATLAB desktop上View選單中的Workspace,Workspace space 瀏覽器可以被檢視。藉由從File選單中選擇Import Data…,或在Command window中鍵入uiimport,輸入精靈(Import wizard)會出現,它是一個使讀取多種格式的資料,而非只是MATLAB原本MAT-file格式的工作變得更容易的通用性GUI。

13.2 資料輸入和輸出(DATA IMPORT AND EXPORT)

除了MATALB原本的MAT-file格式和方便的ASCII文字格式外,MATLAB支援多種工業標準格式和其它常見的檔案格式。有些格式被限制只能讀,而其它的只能寫。有些格式被限制在影像上,其它則是多媒體或是試算表。這些資料輸入和輸出函式和功能使得MATLAB得以與其它程式交換資料。
Figure window的影像可以使用在Figure window File選單上的Save項目來被存為原本的MATLAB FIG-file格式 。此外,Figure window的影像可以藉由選擇Figure window的File選單上的Export…被輸出為各種格式。Command window函式saveas對於以GUI為本的方式提供另一種方法。若需關於使用saveas的輔助,請見線上文件。
在MATLAB中可用的特定資料的輸入和輸出函式包含下表中所列的那些函式。

函式 描述
dlmread 讀取有界定符號的文字檔
dlmwrite 寫入有界定符號的文字檔
textread 從檔案中讀取格式化的文字
wklread 讀取試算表檔案
wklwrite 寫入試算表檔案
xlsread 讀取試算表檔案
aviread 讀取電影(movie)檔
imread 讀取影像檔
imwrite 寫入影像檔
auread 讀取Sun音訊(sound)檔
auwrite 寫入Sun音訊檔
wavread 讀取Microsoft音訊檔
wavwrite 寫入Microsoft音訊檔
hdf 進入HDF檔案的能力

這些函式中的每一個的輔助說明都提供了關於其使用法的資訊。尤其是函式imread和imwrite更支援多種格式。支援的格式包含了JPEG, TIFF, BMP, PNG HDF, PCX和XWD。Fileformats的輔助說明提供了更完整的MATLAB支援的檔案格式列表,例如,

>> help fileformats

Readable file formats.

Text formats Command Returns
MAT – MATLAB workspace load Variables in file.
CSV – Comma separated numbers csvread Double array.
DLM – Delimited text dlmread Double array.
TAB – Tab separated text dlmread Double array.

Spreadsheet formats
XLS – Excel worksheet xlsread Double array and cell array.
WK1 – Lotus 123 worksheet wk1read Double array and cell array.

Movie formats Command Returns
AVI – Movie aviread MATLAB movie.

Image formats
TIFF – TIFF image imread Truecolor, grayscale or indexed image(s).
PNG – PNG image imread Truecolor, grayscale or indexed image.
HDF – HDF image imread Truecolor or indexed image(s).
BMP – BMP image imread Truecolor or indexed image.
JPEG – JPEG image imread Truecolor or grayscale image.
GIF – GIF image imread Indexed image.
PCX – PCX image imread Indexed image.
XWD – XWD image imread Indexed image.
CUR – Cursor image imread Indexed image.
ICO – Icon image imread Indexed image.

Audio file formats
AU – NeXT/Sun sound auread Sound data and sample rate.
WAV – Microsoft Wave sound wavread Sound data and sample rate.

13.3 低階的檔案輸入/輸出(LOW-LEVEL FILE I/O)

因為存在著無限種的檔案型別,MATLAB提供低階檔案I/O函式以便讀取或寫入任何可想見的二元或格式化的ASCII檔案。這些函式非常相佽於它們的ASCIC語言中的對應函式,不過它們的特性並不需要完全配適。事實上,許多上面描述迥的特殊目的檔案I/O命令在內部使用這些函式。在MATLAB中的低階檔案IO函式如下表所示。

類別 函式 描述/語法範例
檔案開啟和關閉 fopen 開啟檔案。fid=fopen(&#039filename&#039, &#039permission&#039)
fclose 關閉檔案。status=fclose(fid)
二元I/O fread 讀取部份或整個二元檔。A=fread(fid,num,precision)
fwrite 將陣列寫到二元檔裡。count=fwrite(fid,num,precision)
格式化I/O fscanf 從檔案讀取格式化資料A=fscanf(fid,format,num)
fprintf 將格式化資料寫到檔案中count=fprintf(fid,format,A)
fgetl 從檔案讀取行;忽略換行字元(newline character)line = fget1(fid)
fgets 從檔案讀取行;保留換行字元(newline character)line = fgets(fid)
字串轉換 sprintf 將格式化資料寫到字串中。S=sprintf(format,A)
sscanf 在格式控制下讀取字串。A=sscanf(String,format,num)
檔案取位 ferror 詢問關於檔案I/O的狀態message=ferror(fid)
feof 測試檔案的結束與否。TF=feof(fid)
fseek 設定檔案位置指示器(indicator)。status=fseed(fid,offset,origin)
ftell 取得檔案位置指示器(indicator)。position=ftell(fid)
frewind 倒回檔案起點frewind(fid)

在上表中,fid是檔案的辨識號碼(identifier number),而permission是用來辨識需求許可的字元字串。可能的字串有唯讀的&#039r&#039、唯寫的&#039w&#039,和只可附加的&#039a&#039,及可讀寫的&#039r+&#039。因為PC個人電腦會區別文字和二元檔,當以二元檔作業時,&#039b&#039一定常常會被加到perssion後面,例如,&#039rb&#039。在上表中是一個定義想要格式的字元字串。Format非常嚴格地遵循ANSI 標準的C。更多關於使用這些函式的資訊可以在每個函式的線上文件中找到。

13.4 目錄管理(DIRECTORY MANAGEMENT)

第6版的MATLAB有全新的視窗,這意味著在GUI中管理目前目錄和其檔案變得可行。藉由從在MATLAB desktop中的View選單選擇Current Directory會顯示Current Directory window。除了在樹狀目錄中逛之外,此GUI讓你預視在目前目錄中的檔案、查看它們被修改的日期、在-file中搜尋文字、建立新目錄和新M-file,等…。因為目前目錄的基本效用,它也可以在MATLAB desktop window中的pop-up選單中被顯示。因此,總可以藉由查看桌面的工具列便能輕鬆地知道目前的目錄。

在第6版之前的MATLAB中,目錄管理經由使用Command window函式來操作。雖然這些函式在第6版中的重要性不如以往,它們仍然提供重要的功能。特別是,大部份的函式有傳回MATLAB內變數的目錄和檔案資訊的能力,因此可讓複雜的檔案和目錄處理在函式M-file中完成。在MATLAB中Command window目錄管理可用的函式整合如下表。

函式 描述
cdpwdS=cd; 顯示目前工作的目錄。傳回目前工作的目錄為S中的字串。
cd dirname 將目前工作的目錄改為dirname。
copyfile(oldname, dirname)copyfile(oldname, newname) 將檔案oldname複製到目錄dirname中。將檔案oldname複製為newname。
delete filename.ext 刪除檔案filename.ext。
dirlsS=dir; 顯示在目前目錄中的檔案。傳回目錄資訊於結構S中。
mkdir dirname 在目前的目錄中建立dirname目錄
WhatS=what; 以組織過的一張表顯示在目前目錄中,所有的MATLAB檔案。傳回資訊列表於結構S中。
which filenameS=which(&#039filename&#039) 顯示filename的目錄路徑。傳回目錄路徑到S中的一個字串filename。
whowho –file filenameS=who (&#039-file&#039, &#039filename&#039) 顯示在workspace中的變數。顯示在MAT-file filename.mat中的變數。傳回在filename.mat的變數於巢狀陣列S中。
whoswhos –file filenameS=whos(&#039-file&#039, &#039filename&#039) 顯示在workspace中的變數、大小和class。顯示在MAT-file filename.mat中的變數、大小和class。傳回在filename.mat的變數、大小和class於巢狀陣列S中。
Help filenameS=help(&#039filename&#039) 在Command window中顯示filename的輔助說明文字。傳回在filename的輔助說明文字到字元字串S中。
type filename 在Command window中顯示M-file。

上述的函式中大部份只需要部作的路徑資訊來找出特定檔案的位置。也就是,可以包括或不包括它的目錄路徑的一部份。如果在filename中沒有目錄路徑被包括,MATLAB搜尋路徑會使用目前的目錄來搜尋所需的檔案。如果已提供了部份的目錄路徑,MATLAB會巡迴MATLAB的搜尋路徑以找出子目錄和指定的檔案。例如,如果filename = &#039mystuff/myfile&#039,」MATLAB限制它的搜尋到MATLAB路徑上名為mystuff的子目錄。
為了說明上述函式的用途,考慮下面的函式mmbytes。

function y=mmbytes(arg)
%MMBYTES Variable Memory Usage. (MM)
% MMBYTES and MMBYTES(&#039base&#039) returns the total memory in bytes
% currently used in the base workspace.
% MMBYTES(&#039caller&#039) returns the total memory in bytes currently
% used in the workspace where MMBYTES is called from.
% MMBYTES(&#039global&#039) returns the total memory in bytes currently
% used in the global workspace.
if nargin==0
arg=&#039base&#039
end
if strcmp(arg,&#039global&#039)
x=evalin(&#039base&#039,&#039whos(&#039&#039global&#039&#039)&#039);
else
x=evalin(arg,&#039whos&#039);
end
y=sum(cat(1,x.bytes));

此函式使用whos函式來收集關於存在於MATLAB內變數的資訊。Whos函式的輸出產生了一個結構陣列x。這個結構的bytes欄位包含了對所有變數的記憶體配置情形。在函式中最後的陳述式將所有已配置的記憶體數目連結為一向量,並以sum函式求得其總和。

因為它各式各樣的使用方式,函式exist並沒有列於上表中。此函式測試變數、檔案、目錄,等等…是否存在。以下是此函式的輔助說明文字,描述了它許多的用法。

>> help exist

EXIST Check if variables or functions are defined.
EXIST(&#039A&#039) returns:
0 if A does not exist
1 if A is a variable in the workspace
2 if A is an M-file on MATLAB&#039s search path. It also returns 2 when
A is the full pathname to a file or when A is the name of an
ordinary file on MATLAB&#039s search path
3 if A is a MEX-file on MATLAB&#039s search path
4 if A is a MDL-file on MATLAB&#039s search path
5 if A is a built-in MATLAB function
6 if A is a P-file on MATLAB&#039s search path
7 if A is a directory
8 if A is a Java class

EXIST(&#039A&#039) or EXIST(&#039A.EXT&#039) returns 2 if a file named &#039A&#039 or &#039A.EXT&#039
and the extension isn&#039t a P or MEX function extension.

EXIST(&#039A&#039,&#039var&#039) checks only for variables.
EXIST(&#039A&#039,&#039builtin&#039) checks only for built-in functions.
EXIST(&#039A&#039,&#039file&#039) checks for files or directories.
EXIST(&#039A&#039,&#039dir&#039) checks only for directories.
EXIST(&#039A&#039,&#039class&#039) checks only for Java classes.

EXIST returns 0 if the specified instance isn&#039t found.

為了能更方便地處理包含了目錄路徑和檔案名稱的字元字串,MATLAB提供數種有用的函式。這些函式被整理如下表。

函式 描述
addpath(&#039dirname&#039) 增加目錄dirname到MATLAB搜尋路徑中。
[path,name,ext]=…fileparts(filename) 傳回filename的路徑、名稱和附加檔名。
filesep 傳回此電腦平台的檔案分隔字元。檔案分隔符號是用來分隔目錄和檔案名稱的字元。例如,在PC上,檔案分隔符號是&#039&#039。
fullfile(d1,d2,…,filename) 使用樹狀目錄的字串,d1,d2,….來傳回filename的完整路徑和檔案規格。
matlabroot 傳回包含MATLAB根目錄的字串。
mexext 傳回此平台下的MEX-file附加檔名。
pathsep 傳回此平台下的路徑分隔符號。路徑分隔符號是在MATLAB搜尋路徑上,用來分隔東西的字元。
prefdir 傳回此平台下MATLAB優先次序目錄。
rmpath(&#039dirname&#039) 從MATLAB的搜尋路徑中移除目錄dirname。
tempdir 傳回此平台下的暫時目錄名稱。
tempname 傳回此平台下的暫時檔案名稱。

這些函式,和上述表中的那些說明,使得建立檔案和目錄管理變得更加容易,就好像M-file一般。藉由查閱線上輔助說明,可以找到更多關於各個函式的輔助。

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 4 則迴響

精通Matlab 6 第十二章 中譯

第十二章 M-file 除錯和效率剖析(M-file Debugging and Profiling)

在發展函式-file的過程中,不可避免的,會有錯誤(也就是bugs)出現。MATLAB提供數種方法和函式來輔助對M-file的除錯(debugging)。MATLAB也提供了幫助你增進M-file執行效率的工具。在剖析一M-file的執行效率時,MATLAB會指哪一行程式碼花費最多的時間來完成。

12.1 除錯工具(DEBUGGING TOOLS)
有二種錯誤類型可能出現在MATLAB表示式中:語法錯誤(syntax errors)和執行期間錯誤(run-time errors)。語法錯誤(譬如誤拼變數或函式名稱或遺失引號或小括號)會在MATLAB評估表示式、或函式被編譯到記憶體裡時被發現。MATLAB即刻標示這些錯誤並且提供回饋關於所遇到類型的錯誤和它發生在M-file中的行數。根據回饋的資訊,通常很容易就能指出這些錯誤。這種情況的例外發生在GUI callback字串中的語法錯誤時。直到字串本身在GUI運作期間被評估之前,這些錯誤很難被偵測出來。

另一方面,即使MATLAB也標示了它們,執行期間錯誤通常更難發現。當發現執行期間錯誤時,MATLAB傳回錯誤給Commnad window和MATLAB workspace。存取錯誤發生的函式workspace的權力已經遺失,因此你不能以孤立問題的方式來質問函式workspace的內容。
根據作者的經驗,最常見的執行期間錯誤發生在某些運算的結果導致空陣列或NaNs時。所有在NaNs上的運算會傳回NaNs,所以如果NaNs有可能為結果,最好使用邏輯函式isnan來在NaN發生時執行某些預設動作。取址空陣列總是導致錯誤,因為空陣列有0維度。Find函式提出一般空陣列為結果的情況。如果find函式的空陣列輸出被用來索引某個其它的陣列,結果也會傳回空。也就是,空矩陣會試著生出空矩陣,例如

>> x=pi*(1:4) % 範例資料
x =
3.1416 6.2832 9.4248 12.5664
>> i=find(x>20) % 使用find函式
i =
[]
>> y=2*x(i) %產生了空矩陣
y =
[]

很清楚地,當y被期望為有限維度和有值,可能會發生執行時間錯誤。當執行運算或使用會傳回空的結果的函式,對於空矩陣的情形,邏輯函式isempty來定義預設結果很有用,因此可避免執行期間錯誤。
要除錯函式M-file有數種方法。對簡單的問題,很直接地的會使用以下的組合。

1. 從在函式內選定的行移除分號,使得即時結果會顯示於Command window中。
2. 在函式中增加顯示感興趣變數的陳述式。
3. 在M-file中選定的位置上放置keyboard命令會暫時將控制權交給鍵盤。這麼做,函式workspace會被質問且如果需要的話,值也會改變。執行return命令在鍵盤提示待足,也就是,k>>return,會恢復函式的執行。
4. 將%放置在M-file開端的函式定義陳述式之前,會將函式M-file變為script M-file。當執行的是script file時,workspace是MATLAB workspace,因此在錯誤發生之後,可以質問它。

當M-file很大、M-file是遞迴的或-file時高度巢狀時,也就是,它會呼叫其它仍舊會呼叫其它函式的M-file函式,函式又一直呼叫函式,最有效率的方式便是使用可在編輯器/除錯器的Debug和Breakpoint選單中找到的MATLAB圖形除錯函式。這些函式存在於與Command window等價的地方,不過使用起來卻更煩人了。如果你堅持使用這些函式而非圖形除錯器,請參見線上輔助說明中關於debug的內容,也就是,>>helpwin debug。

MATLAB中圖形除錯工具允許伙在使用者設定的中斷點(breakpoint)及MATLAB警告和錯誤上,和在會產生NaNs和Infs的表示式上暫停。當到達中斷點時,MATLAB會在受影響的列完成執行前暫停執行並且傳回結果。當暫停時,Command window中的鍵盤提示符號>>會出現,讓你質問函式workspace,改變在workspace內的變數值,等等…追踪出bug需要的所
有動作。除了Editor/Debugger window會顯示暫停執行的行數和提供一步步進入其它被正debug的 M-file呼叫的函式workspace的意義。當你已經移出中斷點時,它會繼續直到到達滑鼠游標位置,或由除錯動作終止為止。
描述使用圖型除錯工具很困難,因為它們的圖形化本質,和因為對於每個除錯節區(sesseion)而言,除錯都是獨一無二的過程。然而,作者發現除錯工具很直覺也很容易使用。一旦精通了基本步驟,MATLAB圖形化的除錯特性,在建立優良的MATLAB程式碼時,會非常地有威力及生產力。

12.2 檔案相依性(FILE DEPENDENCIES)
在已知M-file可以很容易地被電子地傳遞後,會常常見到說,執行M-file發現它執行失敗,只因為它呼叫一個或多個在你的MATLAB路徑中找不到的M-file函式。MATLAB提供函式depfun,它為了檔案相依性會剖析(parse)M-file。此函式遞迴地搜尋所有函式相依性,包括在函式內由其它問題中函式所呼叫的相依性,就好像在握把式圖形物件(Handle Graphic object)內callback任何函式的相依性都可以被找出。例如,考慮下面列出的函式mmlog10。

function [m,e]=mmlog10(x)
%MMLOG10 Dissect Decimal Floating Point Numbers. (MM)
% [M,E]=MMLOG10(X) returns the mantissa M and exponent E of X,
% such that X=M.*(10.^(E)). M is in the range 1
%
% See also LOG2, LOG10

% create output arrays
m=zeros(size(x));
e=m;
% capture exceptions
tmpa=isnan(x); % NaN&#039s
m(tmpa)=nan;
e(tmpa)=nan;
tmpb=isinf(x); % +/- infs
m(tmpb)=1;
e(tmpb)=x(tmpb);
tmpc=(x==0); % 0&#039s
%m(tmpc)=0; e(tmpc)=0; %these values are already zero!
% now for “good" numbers
tmp=~(tmpa|tmpb|tmpc);
e(tmp)=floor(log10(abs(x(tmp))));
e(tmp)=e(tmp)+(abs(x(tmp))>=10.^(e(tmp)+1));
m(tmp)=x(tmp)./10.^e(tmp);

藉由執行下面的命令,在mmlog10內的函式相依性可以被找出。

>> [trace_list,builtins]=depfun(&#039mmlog10&#039,&#039-toponly&#039)
Examining file C:MATLABR12 oolboxmm6mmlog10.m
trace_list =
&#039C:MATLABR12 oolboxmm6mmlog10.m&#039
&#039C:MATLABR12 oolboxmatlabelfunlog10.m&#039

builtins =
&#039size&#039
&#039zeros&#039
&#039isnan&#039
&#039isinf&#039
&#039==&#039
&#039|&#039
&#039~&#039
&#039abs&#039
&#039floor&#039
&#039+&#039
&#039.^&#039
&#039>=&#039
&#039./&#039

預設狀況下,depfun會建立握把式圖形物件(Handle Graphic object)來看看是否問題中的函式儲存任何與握把式圖形物件相關的callback中函式呼叫。很清楚地,mmlog10並沒有,因為它執行陣列算術運算。巢狀陣列變數trace_list包含完整路徑和由mmlog10呼叫的M-file函式的函式名稱列表,包含它自己本身。此巢狀陣列變數builtins包含一連串由mmlog10呼叫的所有內建MATLAB命令。
在呼叫語法中,第二個輸入引數是&#039-toponly&#039。此引數指示depfun要避免遞迴搜尋。換句話說,在此例中,depfun並沒有開啟log10來找出其相依性然後開啟這些相依性,直到它窮究了所有被mmlog10呼叫的函式。沒有第二個引數&#039-toponly&#039,dpfun會需要大量時間且會傳回過度多的資訊量。如果你需要此項資訊,要求depfun分析它所包括的1183行,那麼使用,[trace_list,builtins]=depfun(&#039depfun&#039)。
函式depfun作了窮究性的搜尋。除了上述的二個輸出trace_list和builtins,它也可以傳回其它的資訊。depfun最通用的呼叫語法為

[trace_list, built-ins, class_names, prob_files, prob_symbols,…
eval_strings, called_from, java_classes]=depfun(fun);

在此語法中,class_names是所有用於函式的classes的巢狀陣列;probfiles是不能被剖析(parsed)的檔案結構陣列;prob_symbols是不能被解析為函式變數的符號(symbol)結構陣列;eval_strings是指出tracefiles中的檔案對eval, evalc, evalin或 feval呼叫的結構陣列;called_from是指出誰呼叫唯的巢狀陣列;而java_classes是被trace_list中一個或多個檔案使用的Java class名稱巢狀陣列。

12.3 M-files效能剖析(PROFILING M-FILES)

即使當M-file執行正確,也可能有微調(find-tune)程式碼以避免不需要的計算或函式呼叫的方法。效率改善可由簡單地儲存計算的結果以避免複雜的重覆計算,或鄇用向量化技巧來避免如For迴圈的迭代程序。當搖寫函式時很難猜出大部份執行的時間花費在哪裡。在今日有整合了浮點運算單元的高速處理器,計算結果超過一次可能比儲存變數到磁碟中待稍後取回更快。根據正被處理的資料,它可能比使用更多記憶體來儲存暫時、中介的(intermediate)結果更快,或比執行更多運算更快。再者,介於記憶體和運算間的權衡取捨幾乎總是根據資料集的大小來被考慮。如果函式運算在大型資料集合上,最佳的實作可能會不同於當資料集為小型時的。更複雜的事是已知演算法的最佳實作通常不同於文獻上所寫的演算法。

MATLAB提供效能剖析的(profiling)工具來最佳化M-file函式的執行。這些工具監督著M-file的執行,並且指出哪一行與剩餘的程式碼比起來花費了較多的時間。例如,如果有一行或函式呼叫花費了已知的M-file50%的時間,注意此行或此函式呼叫將會對全面的執行速度有最大的影響。有時你可以重寫程式碼來消除違反效率原則的那幾行。其餘的時候你可以最小化在那行被處理的資料數,因此加快了它的執行速度。且在其它時候,對於增快速度,你可能會沒事可做。無論如何,好的洞悉行為可由效能剖析M-file的運算獲得。
MATLAB使用profile命令來決定在M-file中哪行程式碼花費了最多的執行時間。使用profile是很直接的。例如,可以執行以下的命令來執行mm1og10(之前出現過)的效能剖析

>> profile on
>> for i=1:100
[m,e]=mmlog10(x);
end
>> profile report

首先效能剖析器(profile)會被打開,然後mmlog10被執行充份的次數,最後產了一效能剖析報告。效能剖析報告是一個顯示在Help window或在你電腦預設的瀏覽器中的HTML檔。在作者的電腦上顯示這些mm1og10的細節會有以下的執行摘要 。

Time(s) Percent of time Line No. LineContest
13: % create output arrays
0.05 7% 14: m=zeros(size(x));
15: e=m;
17: tmpa=isnan(x); % NaN’s
0.11 15% 18: m(tmpa)=nan;
0.06 8% 19: e(tmpa)=nan;
0.06 8% 20: tmpb=isinf(x); % +/- infs
21: m(tmpb)=1;
25: % now for “good” numbers
0.06 8% 26: tmp=~(tmpa | tmpb | tmpc);
0.20 28% 27: e(tmp)=floor(log10(abs(x(temp))));
0.05 7% 28: e(tmp)=e(tmp)+(abs(x(tmp))).=10.^(e(tmp)+1);
0.06 8% 29: m(tmp)=x(tmp)./10/^e(tmp);

如上所示,第27行需要最多的時間數。它花費了0.20秒或28%的函式執行所需要的時間。Mmlog10在For迴圈中被執行100次的理由是效能剖析器(profiler)並沒有無限的時間精度(precision)。函式profile一般以0.05秒來作為處理量化時間的單位。結論是,在快速的電腦上,問題中的函式必須被執行多次以累積充份的資料。當For迴圈被由之前的效能剖析例子中消去時,在效能剖析報告中並無有用的資訊。

Profile命令除了上面舉出的那些之外,還有許多特性。有三種詳盡程度可以被選擇。記錄顯示所需要的函式呼叫的時間次序。而統計資料被傳回在結構中。若需更詳盡的關於效能剖析的輔助資料,請參見線上關於profile的輔助說明。

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第十章 中譯

第10章 流程的控制(Control Flow)

電腦程式語言和可程式的計算機提供了讓你根據決策結構去控制命令執行流程的特性。如果你之前已用這這些特性,本節對於你來說會是非常熟悉的。另一方面,如果控制流程對你而言是全新的東西,首次接觸這些材料可能會讓你感到有點複雜。
流程的控制相當有威力,因為它讓過去的計算推論未來的運算。MATLAB提供五種決策制定或控制流程的結構。它們是FOR迴圈(For Loops),While迴圈(While Loops),If-Else-End 結構,Switch-Case結構和Try-Catch區塊。因為這些結構通常包含大量的MATLAB命令,它們通常出現在M-file中,而非在MATLAB提示符號之後被直接鍵入。

10.1 FOR迴圈(FOR LOOPS)

For迴圈會讓一群命令被重覆執行一固定、預先決定的次數。For迴圈的一般型式為
for x=array
(command)
end

對於在array中的每一行,介於for和end陳述式間的(command)都會被執行一次。在每次迭代時,x被指派到array的下一行;也就是,在第n次迴圈時,x=array(:,n)。例如,

>> for n=1:10
x(n) = sin(n*pi/10);
end
>> x
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

換句話說,第一個陳述式的意思是:對於等於1到10評估所有的陳述式,直到下一個end陳述式。第一次進入For迴圈時,n=1,第二次,n=2,…,直到n=10時。在n=10的情況之後,For迴圈會在end陳述式被評估後結束所有的命令,在本例中會去顯示計算後的x元素。

因為迴圈變數被指派到在等號右手邊陣列中連續的行,可能會發生任意地索引或粗心大意的錯誤,考慮下例。

>> for n=10:-1:1 % 遞減的迴圈
x(n)=sin(n*pi/10);
end
>> x
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

在此例中,迴圈變數n從10到1倒數。表示式10:-1:1是標準陣列建立的陳述式,它會建立一個有許多行的列向量。可以使用任何的數值陣列來作為迴圈變數。

>> i=0; % 計算迴圈迭代數
>> for n=(1:10)&#039 %右手方是一行
i=i+1;
x(n)=sin(n*pi/10);
end
>> i % 只有經過迴圈一次!
i =
1
>> x
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

在此例中,For迴圈只有執行一次!表示式(1:10)&#039是個行向量,因此n在迴圈的第一次時被設為(1:10)&#039這整個陣列。因為在右手方沒有其它行,迴圈終止。

>> for n=array
x(n)=sin(n*pi/10);
end
>> x
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

在此例中迴圈變數n以array給定的隨機次序取出數字1到10。
迴圈不能以在迴圈內重新指派迴圈變數n的方式被終止,例如,
for n=1:10
x(n)=sin(n*pi/10) ;
n=10;
end
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

若要重覆,在For迴圈陳述內的右手邊陣列可以是任何有效的陳列建立陳述式,例如,

>> i=1;
>> for x=rand(4,5)
y(i)=sum(x);
i=i+1;
end
>> y
y =
3.0674 2.4343 1.7147 1.1647 1.2735

在此迴圈變數x會被指派到隨機陣列中連續4-by-1的行。因為For迴圈沒有自然的迴圈索引,i會被加1。
當然囉,For迴圈可以如你想要的被巢狀化為巢狀迴圈,例如,

>> for n=1:5
for m=5:-1:1
A(n,m)= n^2 + m^2;
end
disp(n)
end
1
2
3
4
5
>> A
A =
2 5 10 17 26
5 8 13 20 29
10 13 18 25 34
17 20 25 32 41
26 29 34 41 50

上例只是用來舉例說明For迴圈的使用法,並不代表它們是有效率MATLAB程式設計的好例子。只要有相當的陣列解法可用來解決問題,就應該避免使用For迴圈。此相當的陣列解法,稱作向量化(vectorized)解法,通常會大大地增進執行效率。考慮下例,

>> n=1:10;
>> x=sin(n*pi/10)
x =
Columns 1 through 7
0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090
Columns 8 through 10
0.5878 0.3090 0.0000

這二個陳述式複製了以10個角度重覆計算正弦函式的例子。除了會大大地增進執行效率外,上面的向量化解法也更直觀、更容易閱讀,且需要打更少的字。
上面巢狀的For迴圈與下列的向量化程式碼相等。

>> n=1:5;
>> m=1:5;
>> [nn,mm]=meshgrid(n,m);
>> A=nn.^2+mm.^2
A =
2 5 10 17 26
5 8 13 20 29
10 13 18 25 34
17 20 25 32 41
26 29 34 41 50

如第5章討論過的,在執行For迴圈(或While迴圈)前,應該要預先配置陣列。如此做可以最小化所需記憶體配置的數目。例如,在我們之前考慮的第一個例子,每次在For迴圈內的命令被執行,變數x的大小就會增加.這強迫MATLAB在每次經過迴圈時,都要花時間去配置更多記憶體給x。要消除這個步驟,那個For迴圈的例子應該被寫作

>> x=zeros(1,10);
>> for n=1:10
x(n)=sin(n*pi/10);
end

現在每次經過迴圈時,只有x(n)的值需要被改變了。

10.2 WHILE迴圈(WHILE LOOPS)

相對於For迴圈以固定次數去評估一群命令,While迴圈以未定義的次數去評估一群陳述式。
While迴圈的一般型式為

While expression
(commands)
end

只要所有expression內的元素為True時,介於While和end陳述間的(commands)就會被執行。通常評估expression的結果會是純量,不過結果為陣列也是有效力的。在結果為陣列的例子中,結果陣列中所有的元素必須為True。考慮下例。

>> num=0;EPS=1;
>> while(1+EPS)>1
EPS=EPS/2;
num=num+1;
end
>> num
num =
53
>> EPS=2*EPS
EPS =
2.2204e-016

這個例子告訴你一個計算特殊MATLAB變數eps值的方法,eps是在有限精度(finite-precision)的情況下,將eps加上1就產生大於1結果的最小數值。在此我們使用大寫的EPS,所以MATLAB的eps值不會被覆寫。在此例中EPS的啟始值為1。只要(1+EPS)>1為True(非0)時,在While迴圈內命令就會被執行。因為EPS持續地除以2,EPS終究會變得夠小,使得將EPS加上1將不再大於1。(回想一下,這確實會發生,因為電腦使用固定位數來表示數字。雙精度指定大約16位,所以你會期望eps很接近10-16 。)此刻(1+EPS)>1為False(0)且While迴圈會終止。最後,將EPS乘以2倍,因為最後一次除以2使得它太小了。

對於陣列表示式,While迴圈只要當所有在expression內的元素都不為True時才會終止。如果你想要While迴圈在任何元素不為True時便終止,你可以使用函式any,例如,while ~any(expression),這會傳回一個純量的邏輯True,每當有任何陣列的內容為True。

10.3 IF-ELSE-END結構(IF-ELSE-END CONSTRUCTIONS)

很多時候,有好幾列的命令必須根據關係測試的結果而有條件地被評估。在程式語言中,這種邏輯由If-Else-End結構的一些變化來提供。最簡單的If-Else-End結構為

if expression
(command)
end

只要所有expression內的元素為True(非0)時,介於if和end陳述間的(commands)就會被執行。

當expression內包含數個邏輯子表示式(subexpression)時,只需要評估最小的數目的表示式便能決定最後的邏輯狀態。例如,如果expression 是(expression1 | expression2),那麼expression2只有當expression1為False時才會被評估。相似地,如果expression是(expression1 & expression2),那麼只要expression1為False,expression2就不會被評估。

考慮下例,

>> apples=10; % 蘋果的數目
>> cost=apples*25 % 蘋果的價錢
cost =

250
>> if apples>5 % 對於較大宗的購買,會給予2折的折扣
cost=(1-20/100)*cost;
end
>> cost
cost =
200

在有二選一的例子中,If-Else-End結構為

if expression
(commands evaluated if True)
else
(commands evaluated if False)
end

在此當expression為True時,第一個命令集會被評估;而當expression為False時,第二個命令集僧被評估。
當有三個或更多的選項時,If-Else-End結構會是以下的型式

if expression1
(commands evaluated if expression1 is True)
else expression2
(commands evaluated if expression2 is True)
else expression3
(commands evaluated if expression3 is True)
else expression4
(commands evaluated if expression4 is True)
else expression5
.
.
.
else
(commands evaluated if no other expression is True)
end

在最後這一個型式中,只有和第一個遇到的、為True的表示式相關的命令會被評估;保證其餘的關係式不會被測試,且剩餘的If-Else-End結構會被跳過。再者,最後的else命令或許會,或許不會出現。

現在我們知道如何以If-Else-End結構來作決策了,以下告訴你一個合法的方法來跳出For迴圈和While迴圈。

>> for num=1:1000
EPS=EPS/2;
if (1+EPS)
EPS=EPS*2
break
end
end
EPS =
2.2204e-016
>> num
num =
53

這個例子展示了另一個估算EPS的方法。在此例中,For迴圈被指示要去執行一個夠大的次數。If-Else-End結構測試會去看是否EPS已經夠小了。如果它已經夠小了,EPS會乘以2然後break命令會強制迴圈提早結束。在本例中在n=53時會結束。

在此例中,當break陳述式被執行時,MATLAB跳到它所在迴圈外的下個陳述式。在此例中,它會回到MATLAB提示符號之後並且顯示EPS的值。如果break陳述式出現在巢狀For迴圈或While迴圈結果中,MATLAB只會跳出目前它所在的迴圈。它不會跳出整個巢狀結狀。

MATLAB版本6引入了命令continue,它可被用於For迴圈和While迴圈。當MATLAB在For迴圈或While迴圈內遇到了continue陳述式,它立刻跳到此迴圈的結束(end)之處,跳過所有介於continue命令和end陳述式間的命令。如此一來,continue命令立刻移動到迴圈下一回合的測試式。考慮下例

>> EPS=1;
>> for num=1:1000
EPS=EPS/2;
if (1+EPS)>1
continue
end
EPS=EPS*2
break
end
EPS =
2.2204e-016

在此,先前的例子用continue命令重新寫過。注意到continue命令不會對If-End結構造成影響。

10.4 SWITCH-CASE結構 (SWITCH-CASE CONSTRUCTIONS)

當有好幾列的命令必須根據「重覆使用只有一命令引數的等式測試」的結果有條件地評估時,使用Switch-Case結構通常會比較容易。Switch-Case結構有以下的型式

switch expression
case test_expression1
(commands1)
case {test_expression2, test_expression3, test_expression4}
(commmand2)
otherwise
(command3)
end

在此,expression必須是純量或是字元字串。如果expression為純量,expression==test_expressionN會由每個case陳述式測試。如果expression為字元字串,則會測試strcmp(expression,test_expression)。在上例中,expression在第一個case陳述式會和test_expression1相比較。如果它們相等,(command1)會被評估且在end之前剩下的陳述式會被跳過。如果第一個的比較不為True,則會考慮第二個。上例中,expression會和在巢狀陣列中的test_expression2, test_expression3和test_expression4作比較。如果它們中有任一個等於expression,(command2)會被評估且在end之前剩下的陳述式會被跳過。如果所有的case比較皆為false,在選擇性陳述式otherwise之後的(command3)會被執行。

注意到Switch-Case結構的作法讓你至多只能執行那一群的命令(commands)中的一個。
一個簡單的說明Switch-Case結構的例子如下

x=2.7;
units=&#039m&#039
switch units
case{&#039inch&#039,&#039in&#039}
y=x*2.54;
case{&#039feet&#039,&#039ft&#039}
y=x*2.54/12;
case{&#039meter&#039,&#039m&#039}
y=x/100;
case{&#039millimeter&#039,&#039mm&#039}
y=x*10;
case{&#039centimeter&#039,&#039cm&#039}
y=x;
otherwise
disp([&#039Unknown Units:&#039units])
y=nan;
end

執行上例會得到y最後的值為0.027.

10.5 TRY-CATCH區塊(TRY-CATCH BLOCKS)

Try-Catch區塊提供使用者控制偵錯(error-trapping)的能力。也就是,在Try-Catch區塊內,由MATLAB發現的錯誤會被捕捉,給予使用者控制MATLAB如何回應錯誤的能力。Try-Catch區塊有以下型式

try
(command1)
catch
(command2)
end

在此所有在(command1)裡的MATLAB表示式都會被執行。如果沒洧MATLAB錯誤產生,控制權會傳遞給end陳述式。然而,如果當執行(command1)時出現了一個MATLAB錯誤,控制權立即傳到catch陳述式且執行接下來的表示式(command2)。在catch區塊中,函式lasterr包含由在try區塊裡遇到的錯誤所產生的字串。結果,catch區塊表示式(command2)可取出錯誤字串並且根據其內容而動作。

考慮下例為了方便在script M–file裡寫的例子。

x=ones(4,2);
y=4*eye(2);
try
z=x*y;
catch
z=nan;
disp(&#039X and Y are not conformable.&#039)
end
z

以上面和y的資料,此程式碼片段會產生如下的輸出

z =
4 4
4 4
4 4
4 4

在此例中只有在try區塊中的程式碼被執行,改變變數y來製造一個錯誤。

x=ones(4,2);
y=4*eye(3); % 現在y的大小有誤
try
z=x*y;
catch
z=nan;
disp(&#039X and Y are not conformable.&#039)
end
z

執行此刻的程式碼會在Command window中產生下例的輸出。
X and Y are not conformable.
z =
NaN

此外,函式lasterr描述所找到的錯誤。

>> lasterr
ans =
Error using ==> *
Inner matrix dimensions must agree.

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第六章 中譯

第六章 多維度的陣列(Multidimensional Arrays)

在前一章中,已說明了一維和二維陣列及它們的處理方法。因為版本5的MATLAB在幾年前便已出現,MATALB已經增加對任意維度陣列的支援。重要的是,MATLAB讓多維陣列(也就是n維陣列)和一維及二維陣列使用相同的函式和取址技巧。一般來說,第三個維度用頁(pages)來編號,不過更高的維度就沒有通用名稱了。因此,三維陣列有列、行和頁。每頁都包含了一個有列和行的二維陣列。此外,如同在二維陣列的每行都要有相同的列數一樣,每列也要有相同的行數,所有在三維陣列中的頁都要有相同的列數和行數。一個將三維陣列視覺化的方法是將它想成電話簿中的住戶名單(white pages)。每頁都有相同的行數,且每行中都有相同數目的姓名(列數)。所有頁的堆疊構成了一個充滿姓名和電話號碼的三維陣列。

雖然沒有限制維度數目,在本章中大部份還是使用三維陣列,因為它們比較容易視覺化和顯示。

6.1 陣列建構(ARRAY CONSTRUCTION)

多維度的陣列可以用數種方法來建立,例如,
>> A=zeros(4,3,2)
A(:,:,1) =
0 0 0
0 0 0
0 0 0
0 0 0
A(:,:,2) =
0 0 0
0 0 0
0 0 0
0 0 0

這是一個全為0的陣列,它有四列、三行、二頁。首先顯示的是第一頁,接著是第二頁。其它常見的陣列產生函式ones, rand和randn也使用增加輸入引數的方法來增加維度。
直接索引也同樣可行,例如,

>> A=zeros(2,3) % 以二維陣列開始
A =
0 0 0
0 0 0
>> A(:,:,2)=ones(2,3) % 增加第二頁,使它變成三維的!
A(:,:,1) =
0 0 0
0 0 0
A(:,:,2) =
1 1 1
1 1 1
>> A(:,:,3)=4 % 用純量擴展的方式來增加第三頁
A(:,:,1) =
0 0 0
0 0 0
A(:,:,2) =
1 1 1
1 1 1
A(:,:,3) =
4 4 4
4 4 4

上述方法以二維陣列開始,此二維陣列是一個三維陣列的第一頁。然後,用直接陣列取址的方式來增加額外的頁。

函式reshape和repmat也可以用來建立n維陣列,例如,

>> reshape(A,2,9) % 二維陣列,將頁一個靠著一個
ans =
0 0 0 1 1 1 4 4 4
0 0 0 1 1 1 4 4 4
>> B=[A(:,:,1) A(:,:,2) A(:,:,3)] %和上面相同
B =
0 0 0 1 1 1 4 4 4
0 0 0 1 1 1 4 4 4
>> reshape(B,2,3,3) %重新建立A!
ans(:,:,1) =
0 0 0
0 0 0
ans(:,:,2) =
1 1 1
1 1 1
ans(:,:,3) =
4 4 4
4 4 4
>> reshape(B,[2,3,3]) % reshape(B,2,3,3)的另一個表示法
ans(:,:,1) =
0 0 0
0 0 0
ans(:,:,2) =
1 1 1
1 1 1
ans(:,:,3) =
4 4 4
4 4 4

根據上例的說明,reshape可以將任意維度的陣列變成任意其它維度的陣列。

> C=ones(2,3) % 新資料
C =
1 1 1
1 1 1

>> repmat(C,1,1,3) % 這個型式不允許超過二維!
??? Error using ==> repmat
Too many input arguments.

>> repmat(C,[1,1,3])
ans(:,:,1) =
1 1 1
1 1 1
ans(:,:,2) =
1 1 1
1 1 1
ans(:,:,3) =
1 1 1
1 1 1

上面將C在列的維度複製一次,在行的維度複製一次,然後在頁的維度複製三次。

Cat函式可從較低維度的陣列去建立n維陣列。

>> a=zeros(2); % 新資料
>> b=ones(2);
>> c=repmat(2,2,2);
>> D=cat(3,a,b,c) % 沿著第三維度來連結(conCATenate)a,b,c
D(:,:,1) =
0 0
0 0
D(:,:,2) =
1 1
1 1
D(:,:,3) =
2 2
2 2
>> D=cat(4,a,b,c) % 試試第四維度!
D(:,:,1,1) =
0 0
0 0
D(:,:,1,2) =
1 1
1 1
D(:,:,1,3) =
2 2
2 2
>> D(:,1,:,:) %看看第一行內的元素
ans(:,:,1,1) =
0
0
ans(:,:,1,2) =
1
1
ans(:,:,1,3) =
2
2
>> size(D)
ans =
2 2 1 3

D有二列、二行、一頁和三個第四維度的部份。
6.2 陣列的數學和處理(ARRAY MATHEMATICS AND MANIPULATION)

當建立了額外的維度,陣列數學和處理變得更煩人了。純量對陣列的算術運算仍然很直接,不過陣列對陣列算術運算需要二個陣列在所有的維度都具有相同的尺寸大小。因為純量對陣列和陣列對陣列的算術運算仍然和上一章中出現的二維陣列的例子一樣,在此就不再舉例說明。

MATLAB提供數個函式來處理n維陣列。函式squeeze是用來消除singleton dimension;也就是,它消除大小為1的維度。例如,
>> E=squeeze(D) %將維度4擠到維度3中
E(:,:,1) =
0 0
0 0
E(:,:,2) =
1 1
1 1
E(:,:,3) =
2 2
2 2
>> size(E)
ans =
2 2 3

E包含和D相同的資料,不過有二列、二行和三頁。那麼對一個三維的向量會怎麼樣呢?
>> v(1,1,:)=1:6 % 沿著頁維度的一個向量
v(:,:,1) =
1
v(:,:,2) =
2
v(:,:,3) =
3
v(:,:,4) =
4
v(:,:,5) =
5
v(:,:,6) =
6

>> squeeze(v) % 將它擠壓成為一行向量
ans =
1
2
3
4
5
6
>> v(:) % 這總是會建立行向量
ans =
1
2
3
4
5
6

函式reshape允許你在不改變元素總數的情況下,改變列、行和頁及更高維度(order)的尺寸大小,例如,
>> F=cat(3,2+zeros(2,4),ones(2,4),zeros(2,4)) % 新的三維陣列
F(:,:,1) =
2 2 2 2
2 2 2 2
F(:,:,2) =
1 1 1 1
1 1 1 1
F(:,:,3) =
0 0 0 0
0 0 0 0

>> G=reshape(F,[3 2 4]) % 將它變成三列、二行、四頁
G(:,:,1) =
2 2
2 2
2 2
G(:,:,2) =
2 1
2 1
1 1
G(:,:,3) =
1 1
1 0
1 0
G(:,:,4) =
0 0
0 0
0 0

>> H=reshape(F,[4 3 2]) % 將它變成四列、三行、二頁
H(:,:,1) =
2 2 1
2 2 1
2 2 1
2 2 1
H(:,:,2) =
1 0 0
1 0 0
1 0 0
1 0 0

>> K=reshape(F,2,12) % 將它變成二列、12行、一頁
K =
2 2 2 2 1 1 1 1 0 0 0 0
2 2 2 2 1 1 1 1 0 0 0 0

上面的重新塑型(reshape)很煩人直到你能輕易地想像n維空間中的陣列。此外,一些重新塑型的需求比其它的更具實用性。例如,上面的G沒什麼實用性,然而K就比較具體、實用,因為它將F的頁一一靠起來堆疊成為額外的行。

多維陣列的重新塑型(reshape)過程和二維陣列遵守相同的模式(pattern)。首先由列聚集資料,接著再從行,然後是頁,再繼續到更高的維度。也就是說,所有在第一行中所有的列會被聚集,然後在第二行中所有的列再被聚集,…。然後當第一頁被聚集完畢時,會移動到第二頁然後從第一行的所有列再度開始。

陣列元素聚集的順序是函式sub2ind和ind2sub在考慮單索引取址(single index addressing)時的順序:

>> sub2ind(size(F),1,1,1) % 第一列、第一行、第一頁是第1個元素
ans =
1
>> sub2ind(size(F),1,2,1) % 第一列、第二行、第一頁是第3個元素
ans =
3
>> sub2ind(size(F),1,2,3) % 第一列、第二行、第三頁是第19個元素
ans =
19
>> [r,c,p]=ind2sub(size(F),19) % 和上面相反
r =
1
c =
2
p =
3

在n維處理時與flipud和fliplr有相同功能的是flipdim,例如,

>> M=reshape(1:18,2,3,3) %新資料
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18

>> flipdim(M,1) % 翻轉其列的順序
ans(:,:,1) =
2 4 6
1 3 5
ans(:,:,2) =
8 10 12
7 9 11
ans(:,:,3) =
14 16 18
13 15 17

>> flipdim(M,2) % 翻轉其行的順序
ans(:,:,1) =
5 3 1
6 4 2
ans(:,:,2) =
11 9 7
12 10 8
ans(:,:,3) =
17 15 13
18 16 14

>> flipdim(M,3) % 翻轉其頁的順序
ans(:,:,1) =
13 15 17
14 16 18
ans(:,:,2) =
7 9 11
8 10 12
ans(:,:,3) =
1 3 5
2 4 6

函式shiftdim會平移(shift)陣列的維度。也就是說,如果一個陣列有r列,c行和p頁,平移一個維度會產生一個具有c列,p行和r頁的陣列,例如,

>> M %將資料叫回
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18

>> shiftdim(M,1) % 平移一個維度
ans(:,:,1) =
1 7 13
3 9 15
5 11 17
ans(:,:,2) =
2 8 14
4 10 16
6 12 18

平移1個維度使得第一頁的第一列變成了第一頁中的第一行,第一頁中的第二列變成了第二頁中的第一行,…。

>> shiftdim(M,2) % 平移二個維度
ans(:,:,1) =
1 2
7 8
13 14
ans(:,:,2) =
3 4
9 10
15 16
ans(:,:,3) =
5 6
11 12
17 18

在此M的第一頁中的第一行變成了在第一頁中的第一列,第二頁中的第一行變成了第一頁中的第二列,…。如果你像本書作者一樣,你會發現平移維度並不直觀。對於三維的例子而言,如果你能將M想像成長方體的箱子,它的第一頁在前面,然後第二頁在第一頁的後面,然後第三頁形成了箱子的背面,則會有點幫助。然後平移維度就等於旋轉箱子,使得箱子用不同的邊對著你。

函式shiftdim也接受反向的平移。在此例中,陣列被推到更高的維度中,而將singleton dimensions留下,例如,

> M % 將資料叫回來
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18
>> size(M) % M有二列、三行和三頁
ans =
2 3 3

>> shiftdim(M,-1) % 將M向外平移一個維度
ans(:,:,1,1) =
1 2
ans(:,:,2,1) =
3 4
ans(:,:,3,1) =
5 6
ans(:,:,1,2) =
7 8
ans(:,:,2,2) =
9 10
ans(:,:,3,2) =
11 12
ans(:,:,1,3) =
13 14
ans(:,:,2,3) =
15 16
ans(:,:,3,3) =
17 18
>> size(ans)
ans =
1 2 3 3

現在結果有四個維度了。原來的資料和平移後結果的對應就留給讀者來理解囉。

當處理二維陣列時,轉置運算會將列和行交換,將-by-c的陣列轉換成c-by-r的陣列。函式permute和ipermute是在n維處理時等價的運算子。函式permute本身就是函式shiftdim的一般型。考慮下例,

>> M % 將資料叫回來
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18

>> permute(M,[2 3 1]) % 和shiftdim(M,1)相同
ans(:,:,1) =
1 7 13
3 9 15
5 11 17
ans(:,:,2) =
2 8 14
4 10 16
6 12 18

>> shiftdim(M,1)
ans(:,:,1) =
1 7 13
3 9 15
5 11 17
ans(:,:,2) =
2 8 14
4 10 16
6 12 18

上面的[2 3 1]指示函式將第二維變成第一維,第三維變成第二維,且第一維變成第三維。考慮一個較簡單的例子,
>> permute(M,[2 1 3])
ans(:,:,1) =
1 2
3 4
5 6
ans(:,:,2) =
7 8
9 10
11 12
ans(:,:,3) =
13 14
15 16
17 18

在此[2 1 3]指示permute將列和行作轉置,而將第三維保持不變。結果中的每一頁都是原資料的古典轉置。
函式permute中的第二個引數,叫作ORDER,一定要是『傳遞給第一個引數的陣列』其維度的排列;否則所需的排列便沒有意義。考慮下例,

>> permute(M,[2 1 1 ])
??? Error using ==> permute
ORDER cannot contain repeated permutation indices.

>> permute(M,[2 1 4])
??? Error using ==> permute
ORDER contains an invalid permutation index.

函式permute也可以用來將一個陣列推向更高的維度。例如,之前出現的shiftdim(M,-1)等於

>> permute(M,[4 1 2 3])
ans(:,:,1,1) =
1 2
ans(:,:,2,1) =
3 4
ans(:,:,3,1) =
5 6
ans(:,:,1,2) =
7 8
ans(:,:,2,2) =
9 10
ans(:,:,3,2) =
11 12
ans(:,:,1,3) =
13 14
ans(:,:,2,3) =
15 16
ans(:,:,3,3) =
17 18

陣列總會有一個單位維度會超過它的尺寸大小;例如,一個二維的陣列有一個頁。也就是說,所有維度超過陣列的非單位(nonunity)尺寸都只有一(singleton)。結果在上面M中尺寸大小為一的(singleton)第四個維度的作用是用來展示結果的第一維度。

對二維陣列而言,使用轉置運算子二次會傳回原先的陣列。因為n維陣列增加的一般性,函式ipermute用來回復由permute執行的動作。例如,

>> M % 召回資料
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18

>> M=permute(M,[3 2 1]) % 樣本的排列
ans(:,:,1) =
1 3 5
7 9 11
13 15 17
ans(:,:,2) =
2 4 6
8 10 12
14 16 18
>> ipermute(M,[3 2 1]) % 回復到原本的資料(原書上怪怪的!)
ans(:,:,1) =
1 3 5
2 4 6
ans(:,:,2) =
7 9 11
8 10 12
ans(:,:,3) =
13 15 17
14 16 18

6.3 陣列的尺寸大小(ARRAY SIZE)

如前面各章節及本章稍早提過的,函式size傳回陣列每個維度的尺寸大小。由於前一章所說過的特性,size的功能並沒有改變。此外,函式numel也仍未變。考慮下例。

>> size(M) % 傳回陣列的維度
ans =
2 3 3
>> numel(M) % 元素的個數
ans =
18

>> [r,c,p]=size(M) % 傳回個別的變數
r =
2
c =
3
p =
3
>> r=size(M,1) % 只傳回列數
r =
2
>> c=size(M,2) % 只傳回行數
c =
3
>> p=size(M,3) % 只傳回頁數
p =
3
>> v=size(M,4) % 所有更高維度的預設值
v =
1

當維度的數目未知或是一個變數,函式ndims會很有用:
>> ndims(M)
ans =
3
>> ndims(M(:,:,1)) %M的第一個頁是二維的
ans =
2

在此例中,M(:,:,1)是一個二維陣列,因為它只有一頁。也就是說,它有尺寸大小為一(singleton)的第三維。函式ndims等於下列簡單的程式碼,

>> length(size(M))
ans =
3

下表整合了本章中說明過的函式。

N維函式 描述
ones(r,c,…)zeros(r,c,…)rand(r,c,…)randn(r,c,…) 建立基本n維陣列。
reshape(B,2,3,3)reshape(B,[2 3 3]) 將陣列重新塑型成任意維度。
repmat(C[1 1 3]) 將陣列複製成任意維度。
cat(3,a,b,c) 沿著一特定維度來連結陣列。
squeeze(D) 消除尺寸大小為一的維度,也就是,單一(singleton)的維度。
sub2ind(size(F),1,1,1)[r,c,p]=ind2sub(size(F),19) 將下標轉換為單索引(single index)和將單索引轉換成下標。
flipdim(M,1) 沿著所指定維度翻轉。是在n維中功能與flipud和fliplr相同的函式。
shiftdim(M,2) 平移維度。對於正的第二個引數是循環的平移。對於負的第二個引數則是將維度向外推。
permute(M,[2 1 3])ipermute(M,[2 1 3]) 任意排列和將維度反過來。對n維陣列作轉置運算。
size(M)[r,c,p]=size(M) n維陣列各個維度的尺寸大小
r=size(M,1) 陣列的列數
c=size(M,2) 陣列的行數
p=size(M,3) 陣列的頁數
ndims(M) 陣列的維度數
numel(M) 陣列的元素個數

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第五章翻譯

第5章 陣列和陣列運算

在此處考慮的所有計算都已包含了一種叫作純量(scalar)的數。包含純量的運算是數學
的基礎。每當有人需要執行相同的運算或是一次運算在不只一個數上,重覆作純量運算是件既花時間而且煩人的事。為了解決此問題,MATLAB定義了在資料陣列上的運算。

5.1 簡單的陣列
考慮計算正弦函式值的問題,其中x的範圍從0到其週期的一半,也就是說, 且 。因為不可能計算sin(x)在此範圍內所有點上的值(有無限點),我們必須選擇出有限的點來。於是我們對這個函數抽樣。找出一個數來,然後在此範圍內每0.1 計算一次sin(x)的值;也就是說,令 。如果你使用工程計算機來計算這些值,你可能在開始時用list(串列)或陣列來放置這些x值。然後你鍵入每個x值到你的計算機中,找出其正弦值,並且寫下結果到第二個陣列y之中。或許你會有組織地將它們寫成如下表中的型式。

X 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
Y 0 0.31 0.59 0.81 0.95 1 0.95 0.81 0.59 0.31 0

如上表所示,x與y以順序列表;也就是說,y中的第一個值或元素和x中的第一個值或元素有關連,y中的第二個值或元素和x中的第二個值或元素有關連,…。因為有順序,一般以下標來標示在x或y中個別元素的值;例如, 是x中的第一個元素, 是y中的第五個元素,而 是x中的第n個元素。

MATLAB以非常直接、直覺的方式來處理陣列。建立陣列很容易──不過在此記得要遵循上表中的順序:

>> x=[0 .1*pi .2*pi .3*pi .4*pi .5*pi .6*pi .7*pi .8*pi .9*pi pi]
x =
Columns 1 through 7
0 0.3142 0.6283 0.9425 1.2566 1.5708 1.8850
Columns 8 through 11
2.1991 2.5133 2.8274 3.1416

>> y=sin(x)
y =
Columns 1 through 7
0 0.3090 0.5878 0.8090 0.9511 1.0000 0.9511
Columns 8 through 11
0.8090 0.5878 0.3090 0.0000

要在MATLAB中建立陣列,你所要做的就是以「左方括號」開始,鍵入你要的值,並以空間(或是逗號)將這些值分開,然後以「右方括號」結束。注意它會依序找出x中元素的正弦值。MATLAB瞭解你想要找出在x內每個元素的正弦值,並將結果放到相關的陣列y中。這個基本能力使得MATLAB和其它程式語言不同。

由於空格會將陣列中的值分開,當鍵入複數作為陣列中的值的時候,一個複數內不能有空格,除非你是用小括號來圍住它們。例如,[1 –2i 3 4 5+6i]有5個元素,然而[(1-2i) 3 4 5+6i]和[1-2i 3 4 5+6i]這二個相同的陣列只有4個。

5.2 陣列位址或索引(ARRAY ADDRESSING OR INDEXING)
因為在上例中的x有超過一個的元素(它有11個值並分成數行),MATLAB回報給你結果,並指出其相對應的行數。如上所示,x 是一個有1列和11行的陣列,以數學的術語來說,它是個列向量(row vector),一個1by11的陣列,或簡單地說是一個長度(length)為11的陣列。
在MATLAB裡,陣列個別的元素可以以下標存取;例如,x(1)是x的第1個元素,x(2)是x的第2個元素,….。例如,
>> x(3) % x的第3個元素
ans =
0.6283
>> y(5) % y的第五個元素
ans =
0.9511

要一次存取一個區塊的元素,MATLAB提供給你冒號(:)

>> x(1:5)
ans =
0 0.3142 0.6283 0.9425 1.2566

這些是x的第個到第5個元素。標記法1:5說明了是由1數到5。

>> x(7:end)
ans =
1.8850 2.1991 2.5133 2.8274 3.1416

由第7個元素開始,直到最後一個元素。在此end代表x陣列中的最後一個元素。

>> y(3:-1:1)
ans =
0.5878 0.3090 0

這些反向輸出是第3個、第2個和第1個元素。標記法 3:-1:1 說明以3作為啟始,每次遞減1,直到1時停止。

>> x(2:2:7)
ans =
0.3142 0.9425 1.5708

這些是x中的第2個、第4個和第6個元素。標記法2:2:7說明以2開始,每次遞增2,當你遞增到7時結束。在這個例子中,2加6等於8,這大於7,於是第8個元素並不算在內。

>> y([8 2 9 1])
ans =
0.8090 0.3090 0.5878 0

在此使用了另一個陣列[ 8 2 9 1 ],是以我們要的順序來擷取陣列y中的元素。第一個取出的元素是第8個,第二個取出的是第2個,第三個取出的是第9個,而第四個取出的是第1個。實際上[8 2 9 1]本身便是一個代表y中所要元素位址的陣列。
>> y([1 1 3 4 2 2])
ans =
0 0 0.5878 0.8090 0.3090 0.3090

如上所示,陣列並不需要用獨一無二的元素來當作索引。這允許我們任意地重新排列和複製陣列元素。使用此特性能有效地從事MATLAB編程。

用另一個陣列來當作一個陣列的位址是可行的,只要被當作位址的那個陣列中的元素都界於1和陣列的長度(length)之間。舉例說明,

>> y(3.2)
Warning: Subscript indices must be integer values.
ans =
0.5878

>> y(3.7)
Warning: Subscript indices must be integer values.
ans =
0.8090

>> y(11.6)
Warning: Subscript indices must be integer values.
??? Index exceeds matrix dimensions.

在上例中,MATLAB可以接受非整數的索引值,但會給予警告訊息。此外,MATLAB會試著四捨五入到最接近的整數值,然後傳回此值給y當作索引。對於上頭的最後一個例子來說,11.9會被四捨五入成12,而因為y中沒有第12個元素,所以會傳回錯誤訊息替代數值結果。

5.3 建構陣列(ARRAY CONSTRUCTION)

之前我們藉由鍵入個別x元素的值來輸入x的值。不過還好在x內只有11個值,如果有111個值時怎麼辦?使用冒號吧!以下有另外二種輸入x的方法:

>> x=(0:0.1:1)*pi
x =
Columns 1 through 7
0 0.3142 0.6283 0.9425 1.2566 1.5708 1.8850
Columns 8 through 11
2.1991 2.5133 2.8274 3.1416

>> x=linspace(0,pi,11)
x =
Columns 1 through 7
0 0.3142 0.6283 0.9425 1.2566 1.5708 1.8850
Columns 8 through 11
2.1991 2.5133 2.8274 3.1416

在上面的第一個例子中,冒號(0:0.1:1)會建構一個由0開始,每次遞增0.1並以1結束的一個陣列。在此陣列中的每個元素然後再乘以 來建立想要的值。在第二個例子中,MATLAB函式linspace是用來建立x的,這個函式的引數描述如下:
linspace(first_value, last_value, number_of_values)

這二種陣列建構的方式在MATLAB裡都是常見的。冒號型允許你直接指定資料點間的遞增量,而非資料點的數量。另一方面,linspace允許你直接指定資料點的數量而非資料點間的遞增量。

以上的陣列建構方式都可以讓陣列內的元素兩兩間以等間隔的方式產生。對於特殊狀況需要產生以對數(logarithmically)等間隔的陣列時,MATLAB提供了logspace函式:

>> logspace(0,2,11)
ans =
Columns 1 through 7
1.0000 1.5849 2.5119 3.9811 6.3096 10.0000 15.8489
Columns 8 through 11
25.1189 39.8107 63.0957 100.0000

在此,我們建構了一個以 開始, 結束,並含11個值的陣列。這個函式的引數描述如下:

logspace(first_exponent, last_exponent, number_of_values)

雖然一般都以整數10的冪次來開始和結束,logspace在非整數的情況下依然能運算的很好。

當使用冒號或函式linspace及logspace時,通常會想要用方括號將表示式圍起來,例如,

>> a=[1:7]
a =
1 2 3 4 5 6 7

>> b=[linspace(1,7,5)]
b =
1.0000 2.5000 4.0000 5.5000 7.0000

然而使用方括號並不會改變結果,而且可能會增加述敘的可讀性,增加的方括號會強迫MATLAB做更多事且花費了更多的時間,因為方括號代表了連結(concatenation)。在上例中並沒有連結的動作被執行,因此並不需要要求MATLAB花費時間在考慮是否要連結的這個可能性上頭。

小括號並不代表連結(concatenation),因此不會讓MATLAB變慢。結論是,當有必要時,小括號可以被使用,例如,

>> a=(1:7)&#039 %將列改成行
a =
1
2
3
4
5
6
7

有時候會需要那種不容易用線性(linearly)或對數(logarithmically)等間隔元素的關係來描述的陣列。建立這些陣列並沒有一定的方法。然而,陣列位址和其結合表示法的能力可以幫助讓你不用一次鍵入一個元素。例如,

>> a=1:5, b=1:2:9
a =
1 2 3 4 5

b =
1 3 5 7 9

建立了二個陣列。要記得可以在一行裡出現數個敘述,只要將它們以逗號或分號隔開即可。

>> c=[b a]
c =
1 3 5 7 9 1 2 3 4 5

建立了一個陣列c,此陣列由b後緊跟著a而構成。

MATLAB簡單的陣列建構特性整合如下表:

陣列建構技巧 描述
x=[2 2*pi sqrt(2) 2-3j] 建立包含任意元素的列向量x
x=first:last 建立以first開始,一次遞增,並以last結束的列向量x。注意到x=[first:last]也能產生同樣的結果,不過會花費較長的時間,因為MATLAB會考慮方括號和冒號二種陣列建構型式
x=first: increment : last 建立以first開始,一次遞增increment,並以last作為結束的列向量x
x=linspace(first, last, n) 建立以first開始,並以last作為結束,總共有n個元素的線性等間隔的列向量x
x=logspace(first, last, n) 建立以 開始,並以 作為結束,總共有n個元素的對數等間隔的列向量x

5.4陣列導向(ARRAY ORIENTATION)

在上例中,陣列包含一列和數行。這種列導向(row oriented)的結果一般稱之為列向量(row vector)。當然也有可能是一個陣列是個有一行和數列的行向量(column vector)。在這種情況下,所有之前的陣列處理和數學運算都不需改變。唯一的差別在於結果的顯示是以行而非以列。因為之前舉出的陣列建構方法都是建立列向量,一定要有某種方法來建立行向量才行。建立行向量最直接的方式就是逐元素地指定它並且使用分號來分開這些值:

>> c=[1;2;3;4;5]
c =
1
2
3
4
5

根據此例,以空格或逗點來分隔的元素代表在不同行的元素,而被分號分隔的元素代表在不同列上的元素。

要使用冒號start : increment : end或函式linspace和logspace來建立一個行向量,你必須要使用MATLAB的轉置(transpose)運算子(’)來將結果的列轉置為行。例如,

>> a=1:5
a =
1 2 3 4 5

用冒號型式來建立了一列向量。

>> b=a&#039
b =
1
2
3
4
5

使用轉置運算子來改變列向量a成為行向量b。
w=b’
w =
1 2 3 4 5

則再次套用轉置並且將行變回列。

除了上面簡單的轉置外。MATLAB也提供了一種前置句號的轉置運算子。前置句號的轉置運算子(dot-transpose operator)被解釋為「非複數的共軛轉置(noncomplex conjugate transpose)」。當一陣列為複數,其轉置(&#039)會產生複數共軛轉置,也就是虛部的正負號會在轉置運算時改變。相對的,前置句號的轉置運算子(dot-transpose operator)則將陣列轉置但不共軛。

>> c=a.&#039

c =
1
2
3
4
5

告訴你 .&#039 和 &#039 在實數時是相同的。

d =
Columns 1 through 4
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i 4.0000 + 4.0000i
Column 5
5.0000 + 5.0000i

從陣列a建立了一個簡單的複數列向量,其中預設的i= 。
>> e=d&#039
e =
1.0000 – 1.0000i
2.0000 – 2.0000i
3.0000 – 3.0000i
4.0000 – 4.0000i
5.0000 – 5.0000i

建立了行向量e是d的複數共軛轉置。

>> f=d.&#039
f =
1.0000 + 1.0000i
2.0000 + 2.0000i
3.0000 + 3.0000i
4.0000 + 4.0000i
5.0000 + 5.0000i

建立了行向量f是d的轉置。

如果陣列可以是一個列向量或一個行向量,很直覺的,陣列也可以是同時有數列及數行。也就是說,陣列也可以有矩陣的型式。矩陣的建立方法遵循著行及列的建立方法。逗號或空格被用來分隔在同一列中的元素,而分號被用來分隔在不同列中的元素:

>> g=[1 2 3 4;5 6 7 8]
g =
1 2 3 4
5 6 7 8

在此g是一個陣列或是一個有2列4行的矩陣;也就是說,它是個2-by4的矩陣或它是個尺寸為2乘4的矩陣。分號告訴MATLAB要在4和5之間開啟一新的列。

>> g=[1 2 3 4
5 6 7 8
9 10 11 12]

g =

1 2 3 4
5 6 7 8
9 10 11 12

除了分號之外,當鍵入陣列時按下Return或Enter鍵也是告訴MATLAB要去開啟新的一列。

>> h=[1 2 3; 4 5 6 7]
??? Error using ==> vertcat
All rows in the bracketed expression must have the same
number of columns.

MATLAB嚴格強制每一列都要有同樣的行數。

5.5 純量陣列的數學運算(SCALAR-ARRAY MATHEMATICS)

在上面的第一個陣列的例子中,是以陣列x乘以純量 。其它純量與陣列間簡單的數學運算也可以很自然地被解釋。此外,純量的減法、乘法和除法也可輕易地套用到對整個陣列的元素的運算上。

>> g-2
ans =
-1 0 1 2
3 4 5 6
7 8 9 10

從g的每個元素上減去2。

>> 2*g-1
ans =
1 3 5 7
9 11 13 15
17 19 21 23

將g中的每個元素乘以2作為結果,然後將結果中的每個元素再減去1。

>> 2*g/5+1
ans =
1.4000 1.8000 2.2000 2.6000
3.0000 3.4000 3.8000 4.2000
4.6000 5.0000 5.4000 5.8000

將g中的每個元素乘以2,然後將結果的每個元素再除以5,最後再加1到每個元素上。

注意,純量對陣列的數學運算優先次序和在純量表示式上的用法是一致的,[譯註]也就是先乘除後加減。

5.6 陣列對陣列的數學運算

陣列間的數學運算並不像陣列和矩陣間的運算般簡單。清楚地說,不同大小或尺寸陣列間的陣列運算很難去定義且有更多未定的值。然而,當二個陣列具有相同尺寸時,加法、減法、乘法、除法都能逐元素地套用在MATLAB上,舉例來說,

>> g %叫回之前的陣列
g =
1 2 3 4
5 6 7 8
9 10 11 12

>> h=[1 1 1 1 ; 2 2 2 2 ; 3 3 3 3 ] %建立新陣列
h =
1 1 1 1
2 2 2 2
3 3 3 3

>> g+h %將h逐元素地加到g
ans =
2 3 4 5
7 8 9 10
12 13 14 15

>> ans-h %將之前的答案減去h以求得g
ans =
1 2 3 4
5 6 7 8
9 10 11 12

>> 2*g-h %將g乘以2,再從結果減去h
ans =
1 3 5 7
8 10 12 14
15 17 19 21

>> 2*(g-h) %利用小括號來改變計算的順序
ans =
0 2 4 6
6 8 10 12
12 14 16 18

注意到陣列對陣列的數學運算也使用純量表示式上決定優先次序的方法,而小括弧可用來改變運算的次序。

逐一元素對元素的乘法和除法也以相似的方法計算,不過使用稍微非傳統的符號:

>> g.*h
ans =
1 2 3 4
10 12 14 16
27 30 33 36

在此我們將陣列g和h逐元素地相乘,使用點乘法符號 .*。

在星號(*)之前的句號(.)告訴MATLAB執行逐一元素對元素的陣列乘法。沒有句號(.)的乘法代表矩陣乘法,稍後我們將會討論。

對這個例子而言,矩陣乘法並未被定義:

>> g*h
??? Error using ==> *
Inner matrix dimensions must agree.

逐一元素對元素的除法,或稱之為點除法(dot division),也需要使用句號,例如,

>> g./h
ans =
1.0000 2.0000 3.0000 4.0000
2.5000 3.0000 3.5000 4.0000
3.0000 3.3333 3.6667 4.0000

>> h.g
ans =
1.0000 2.0000 3.0000 4.0000
2.5000 3.0000 3.5000 4.0000
3.0000 3.3333 3.6667 4.0000

除法被定義可以與純量左除(forward slash)和右除(backward slash)。在上面的二個例子中,在短斜線(slash)上面的陣列都除以在下面的陣列。

在右或左短斜線之前的點符號告訴MATLAB執行元素對元素逐一的陣列除法。沒有點的除法代表反矩陣,稍後將討論。

陣列或點除法也可套用在當分子為純量的時候,例如,
>> 1./g
ans =
1.0000 0.5000 0.3333 0.2500
0.2000 0.1667 0.1429 0.1250
0.1111 0.1000 0.0909 0.0833

在此例中,分子中的純量1被擴展成和分母一樣大小的陣列,然後執行元素對元素逐一相除。也就是上頭的表示法是一種計算時的速寫法。

>> f=[1 1 1 1 ; 1 1 1 1 ; 1 1 1 1]
f =
1 1 1 1
1 1 1 1
1 1 1 1

>> f./g
ans =
1.0000 0.5000 0.3333 0.2500
0.2000 0.1667 0.1429 0.1250
0.1111 0.1000 0.0909 0.0833

>> f./h
ans =
1.0000 1.0000 1.0000 1.0000
0.5000 0.5000 0.5000 0.5000
0.3333 0.3333 0.3333 0.3333

自動擴展純量值使元素對元素的算術運算被套用的過程稱作是純量擴展(scalar expansion),純量擴展在MATLAB中大量地被運用。

沒有點的除法是矩陣除法運算,是完全不一樣的運算,例如,

>> g/h
Warning: Rank deficient, rank = 1 tol = 5.3291e-015.
ans =
0 0 0.8333
0 0 2.1667
0 0 3.5000

>> h/g
Warning: Rank deficient, rank = 2 tol = 1.8757e-014.
ans =
-0.1250 0 0.1250
-0.2500 0 0.2500
-0.3750 0 0.3750

矩陣除法所得的結果尺寸大小並不需要和g和h相等。矩陣運算會在矩陣代數的章節中討論。
矩陣的冪次方(exponentiation)也以數種方式定義。就像乘法和除法一樣,^保留給矩陣冪次而 .^ 則是用於元素對元素逐一的冪次方。當冪次方為純量時,純量被套用到陣列中的每個元素上。例如,

>> g,h
g =
1 2 3 4
5 6 7 8
9 10 11 12
h =
1 1 1 1
2 2 2 2
3 3 3 3
>> g.^2
ans =
1 4 9 16
25 36 49 64
81 100 121 144

將g個別的元素平方,然而

>> g^2
??? Error using ==> ^
Matrix must be square.

是矩陣的冪次(exponentiation),只有定義在方陣(square matrix)之上,也就是矩陣的列數需和行數相同。

>> g.^-1

ans =
1.0000 0.5000 0.3333 0.2500
0.2000 0.1667 0.1429 0.1250
0.1111 0.1000 0.0909 0.0833

會找到g中每個元素的倒數(reciprocal)。

>> 1./g
ans =
1.0000 0.5000 0.3333 0.2500
0.2000 0.1667 0.1429 0.1250
0.1111 0.1000 0.0909 0.0833

會和之前見到的的純量擴展有相同的結果。

當冪次方是一個陣列且作用在一純量上時,陣列中的每個元素都會套用到純量上。例如,

>> 2.^g
ans =
2 4 8 16
32 64 128 256
512 1024 2048 4096

產生了2對陣列g中每個元素值的次方。

如果是二個等大小的陣列時,冪次方則會元素對元素逐一地被套用,例如,

>> g.^h
ans =
1 2 3 4
25 36 49 64
729 1000 1331 1728

產生了的元素對應到h的元素。在此例中,第一列並沒有改變,因為h的第一列都是1;第二列被平方了,而第三列變成立方了。

>> g.^(h-1)
ans =
1 1 1 1
5 6 7 8
81 100 121 144

表示純量運算和陣列運算可以合併。

二種冪次型中有純量的部份都仍是純量擴展的衍生例。結果很直觀,如果有純量則先將其擴展成和陣列一樣的大小,然後元素對元素逐一冪次方。

下表整合了陣列的基本運算。

元素對元素的運算 代表的資料A = [ a1 a2 … an ]B = [ b1 b2 … bn ]c =
純量加法 A+ c =[ a1+c a2+c … an+c]
純量減法 A- c =[ a1- c a2- c … an- c]
純量乘法 A *c = [ a1*c a2 *c … an *c]
純量除法 A/ c = cA = [ a1/c a2/c … an/c]
陣列加法 A.+B = [a1+b1 a2+b2 … an+bn]
陣列乘法 A.*B = [a1 *b1 a2 *b2 … an *bn]
陣列右除法 A./B = [a1/b1 a2/b2 … an/bn]
陣列左除法 A.B = [a11 a22 … ann]
陣列冪次法 A.^c = [a1^c a2^c … an+^c]c.^A = [c^a1 c^a2 … c^an]A.^B = [a1^b1 a2^b2 … an^bn]

5.7 標準陣列

因為一般用途所致,MATLAB提供了建立數種標準陣列的函式。其中有那種元素全為1和全為0的陣列、單位矩陣(identity matrices)、隨機數矩陣、對角陣列、和其內元素為特定常數的陣列。

>> ones(3)
ans =
1 1 1
1 1 1
1 1 1

>> zeros(2,5)
ans =
0 0 0 0 0
0 0 0 0 0

>> size(g)
ans =
3 4

>> ones(size(g))
ans =
1 1 1 1
1 1 1 1
1 1 1 1

當以一個引數來呼叫ones(n)或zeros(n) 時,MATLAB會建立n乘n的陣列,根據所呼叫的函式,陣列內會全包含0或全包含1。當以二個引數來呼叫ones(r,c)或zeros(r,c)時,MATLAB會建立一個具有r列c行的陣列。要建立和另一個陣列同樣大小的全為的矩陣或全為0的矩陣,只要在ones或zeros的引數內使用size函式(在本章稍後將會討論到)。

>> eye(4)
ans =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

>> eye(2,4)
ans =
1 0 0 0
0 1 0 0

>> eye(4,2)
ans =
1 0
0 1
0 0
0 0

如上所示,函式eye使用和產生zeros或ones陣列相同的語法風格,來產生了單位矩陣(identity matrices)。一個單位矩陣或陣列是個除了元素A(i,i)之外全為0的矩陣或陣列,其中i=1:min(r,c),而min(r,c)代表A中最小的列數或行數。

>> rand(3)
ans =
0.9501 0.4860 0.4565
0.2311 0.8913 0.0185
0.6068 0.7621 0.8214

>> rand(1,5)
ans =
0.4447 0.6154 0.7919 0.9218 0.7382

>> b=eye(3)
b =
1 0 0
0 1 0
0 0 1

>> rand(size(b))
ans =
0.1763 0.9169 0.0579
0.4057 0.4103 0.3529
0.9355 0.8936 0.8132

函式rand會產生均勻分佈(uniformly distributed)的隨機陣列,且其元素值介於0與1之間。

>> randn(2)
ans =
-0.4326 0.1253
-1.6656 0.2877

>> randn(2,5)
ans =
-1.1465 1.1892 0.3273 -0.1867 -0.5883
1.1909 -0.0376 0.1746 0.7258 2.1832

另一方面,函式randn會產生陣列,且其元素是由平均數為0(zero-mean),變異數為1(unit-variance)的常態分佈中抽樣 。

>> a=1:4 %以一簡單的向量開始
a =
1 2 3 4

>> diag(a) %將元素放置到對角線中
ans =
1 0 0 0
0 2 0 0
0 0 3 0
0 0 0 4

>> diag(a,1) %將元素放到對角線上一行
ans =
0 1 0 0 0
0 0 2 0 0
0 0 0 3 0
0 0 0 0 4
0 0 0 0 0

>> diag(a,-2) %將元素放到對角線下二行
ans =
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0
0 2 0 0 0 0
0 0 3 0 0 0
0 0 0 4 0 0

如上所示,函式diag建立對角陣列,其中向量可以放置在任何平行於陣列主對角線的位置。
看了以上的標準陣列後,你會發現有許多方法可以用來建立元素有相同值的陣列。例如有以下方法,

>> d=pi; % 選擇pi作為例子
>> d*ones(3,4) % 最慢的方法(純量對陣列的乘法)
ans =
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416

>> d+zeros(3,4) % 較慢的方法(純量對陣列的加法)
ans =
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416

>> d(ones(3,4)) % 較快的方法(陣列取址,array addressing)
ans =
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416

>> repmat(d,3,4) % 最快的方法(最佳化陣列取址)
ans =
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416

對於小型陣列而言,上述的方法都還算不錯。不過,當陣列的大小增加時,純量乘法會使得整個程序慢下來。因為加法通常比乘法快些,於是將想要的純量值加到全為0的陣列變為稍為好些的方法。雖然它們並不直觀,最後的二個方法對於大型陣列而言是最快的。它們都包含了之前提過的陣列取址。

解決方法d(ones(r,c)建立了r列c行的內全含1的陣列,然後使用這個陣列來取址並且複製純量d。建立暫時的ones陣列既花費時間且會耗記憶體,因此會使這個方法慢下來,儘管其中並沒有用到浮點運算。而解決方法repmat(d,r,c)呼叫函式repmat,這代表了「複製矩陣」。對於純量d,這個函式會執行以下的步驟。

D(r*c) = d; % 一個列向量,其第(r*c)個元素是d
D(:) = d; % 將所有D的元素都純量擴展為d
D = reshape(D,r,c); % 將向量變型為想要的r列c行

以上的MATLAB程式碼用純量擴展來建立一個有r*c個元素的向量,其中所有的元素都為d。這個向量然後利用函式reshape來變型為r列c行的陣列。函式repmat和reshape在之後會討論到。

5.8 陣列處理
由於MATLAB以陣列為基礎,在MATLAB有許多方法來處理它們。一旦陣列形成,利用有趣的下標,MATLAB提供強大有力的方法來插入、取出及重新排列子陣列。這些特性的知識是你能否有效地使用MATLAB的關鍵。要舉例說明MATLAB陣列處理的特色,考慮以下的例子。

>> A=[ 1 2 3; 4 5 6; 7 8 9 ]
A =
1 2 3
4 5 6
7 8 9

>> A(3,3)=0 % 將第三列,第三行的元素設為0
A =
1 2 3
4 5 6
7 8 0

將第三列第三行的元素變為0。

>> A(2,6)=1
A =
1 2 3 0 0 0
4 5 6 0 0 1
7 8 0 0 0 0

將1放置到第二列,第六行。因為A沒有第六行,於是A的大小會在需要時增加,並且以0填滿,使得陣列維持長方形。

>> A(:,4)=4
A =
1 2 3 4 0 0
4 5 6 4 0 1
7 8 0 4 0 0

將A的第四行設為4因為4是純量,它會被擴展以便能填滿所有指定的元素。這是另一個純量擴展的例子。MATLAB執行純量擴展來簡化那些可能被解釋得模稜兩可的陳述句。例如,以上的陳述句與下面這句更煩人的寫法是等價的。

>> A(:,4)=[4;4;4]
A =
1 2 3 4 0 0
4 5 6 4 0 1
7 8 0 4 0 0

>> A(:,4)=[4 4 4]
??? In an assignment A(:,matrix) = B, the number of elements in the subscript of A and the number of columns in B must be the same.

讓我們再看看其它的陣列處理吧。

>> A=[ 1 2 3; 4 5 6; 7 8 9 ]; % 回復原始資料

>> B=A(3:-1:1,1:3)
B =
7 8 9
4 5 6
1 2 3

>> B=A(end:-1:1,1:3) % 和上頭一樣
B =
7 8 9
4 5 6
1 2 3

把A中的列順序顛倒後,就立了陣列B。end這個字在已知大小的情況下,就自動代表了最後或最大的索引值。在此例中,end表示最大的列索引值3。

>> B=A(3:-1:1,:)
B =
7 8 9
4 5 6
1 2 3

也是和上例一樣的意思。在此最後單一的冒號代表取所有的行。也就是說,在此例中:等價於1:3,因為A有三行。

>> C=[A B(:,[1,3])]
C =
1 2 3 7 9
4 5 6 4 6
7 8 9 1 3

藉由連結B中所有在第一和第三行中的列於A的右方,建立了C。

>> B=A(1:2,2:3)
B =
2 3
5 6

>> B=A(1:2,2:end)
B =
2 3
5 6

擷取A中前二列和後二行能產生B。冒號再次建立索引向量,這索引向量能指定要擷取出的陣列元素。在上頭第二個例子,end被用來代表最後或最大的行索引。

>> C=[1 3]
C =
1 3
>> B=A(C,C)
B =
1 3
7 9

使用陣列C來索引陣列A,而非用冒號start:increment:end或start:end來直接指定它們。在此例中,B由A的第一和第三列及第一和第三行形成。

>> B=A(:)
B =
1
4
7
2
5
8
3
6
9

依序一次取A的一行,將A拉成了行向量B。這是將陣列轉型(reshape)成另一個具有不同尺寸但有相同總元素個數的陣列最簡單的型式。

>> B=B.&#039
B =
1 4 7 2 5 8 3 6 9

>> B=reshape(A,1,9) % 轉型為1-by-9(一列九行)
B =
1 4 7 2 5 8 3 6 9

>> B=reshape(A,[1 9])
B =
1 4 7 2 5 8 3 6 9

說明了之前介紹過的點轉置(dot-transpose)和函式reshape。在此例中,reshape和索引值一同作用,這索引值可當作是個別的函式引數或是被當作是一個單一向量的引數。

>> B=A % 將A複製到B
B =
1 2 3
4 5 6
7 8 9
>> B(:,2)=[]
B =
1 3
4 6
7 9

藉由刪去所有在原矩陣B中第二行中所有列來重新定義B。當你將某些東西設為空矩陣或空陣列[ ]。它會被刪去,導致陣列會將剩餘的元素褶疊(collapse)起來。注意到你必須刪去整列或整行,使結果保持長方形。

>> C=B.&#039
C =
1 4 7
3 6 9
>> reshape(B,2,3) % 變型並不等於轉置
ans =
1 7 6
4 3 9

說明任何陣列的轉置且證明和變型(reshpae)並不相等。轉置會將第i列轉換為結果的第i行,因此原來的三列二行(3-by-2)的陣列變成了二列三行(2-by-3)的陣列。

>> C(2,:)=[]
C =
1 4 7

刪去了C的第二列,留下了個列向量。

>> A(2,:)=C
A =
1 2 3
1 4 7
7 8 9

將A的第二列取代為C。

>> B=A(:,[2 2 2 2]) %建立新的B陣列
B =
2 2 2 2
4 4 4 4
8 8 8 8
>> B=A(:,2+zeros(1,4)) %[2 2 2 2] = 2+zeros(1,4)
B =
2 2 2 2
4 4 4 4
8 8 8 8
>> B=repmat(A(:,2),1,4) % 將A的第二行複製為4行
B =
2 2 2 2
4 4 4 4
8 8 8 8

以三種方式來建立B,都是將A中第二列中的所有列複製四次。最後一種對於大型陣列而言是最快的方法。

>> A, C % 再次印出A和C
A =
1 2 3
1 4 7
7 8 9
C =
1 4 7
>> A(2,2)=[]
??? Indexed empty matrix assignment is not allowed.
<??? 並不允許索引到空矩陣的指派>

告訴你只能刪去整列或整行。MATLAB完全不知道如何去褶疊(collapse)一個部份列或行被刪除了的陣列。

>> C=A(4,:)
??? Index exceeds matrix dimensions.

因為A沒有第四列,MATLAB不知道要做什麼故有此訊息。根據此結果,索引必須遵守下列的指導方針:

如果A(r,c)出現在等號的左方並且被(r,c)指定的元素有一或多個不存在,則0會在需要時被加到A中,使得A(r,c)能取址到已知的元素。不過,在等號右方所有被A(r,c)取址的元素必須是存在的,否則會回報錯誤。

讓我們繼續考慮以下的例子。

>> C(1:2,:)=A
??? In an assignment A(matrix,:) = B, the number of elements of the subscript in A and number of rows in B must be the same.

告訴你不能將一個陣列硬塞(squeeze)到另一個不同大小的陣列中。

>> C(3:4,:)=A(2:3,:)
C =
1 4 7
0 0 0
1 4 7
7 8 9

但是你可以放置A的第二和第三行到C中相同大小的區域中。因為C中的第二到第四列不存在,它們會在需要時被建立。而C的第二列並未被指定,所以它用0填滿。

>> A=[1 2 3; 4 5 6; 7 8 9] % 更新資料
A =
1 2 3
4 5 6
7 8 9
>> A(:,2:3) % 偷看一下等一下要放的是什麼
ans =
2 3
5 6
8 9
>> G(1:6)=A(:,2:3)
G =
2 5 8 3 6 9

藉由取出在A中第二和第三行中的所有列來建立列向量G。注意到在等號二邊的矩陣形狀並不相同。A的元素被插入到G中,A中第一行的元素會變為G中的列,然後A中第二行的元素會接在此列之後。

>> H=ones(6,1); %建立一行向量
>> H(:)=A(:,2:3) %用A來填H而不改變其形狀
H =
2
5
8
3
6
9

當(:)出現在等號左方時,它代表從等號右方取出元素,並且在不改變等號左方陣列形狀的情況,將元素填入等號左方的陣列中。上例中將A第二和第三行取出並插入H的行向量中。顯然地,上述的動作必須在等號二邊有相同的元素個數時才可發生。

當等號右手邊是純量和左手邊是陣列時,會使用純量擴展(scalar-expansion)。例如,

>> A(2,:)=0
A =
1 2 3
0 0 0
7 8 9

會將A的第二列取代為0。右手邊的0會被擴展以便填滿左方所有指定的位置。這個例子等於:

>> A(2,:)=[0 0 0]
A =
1 2 3
0 0 0
7 8 9

每當陣列的位置需要放置純量時,會發生純量擴展。MATLAB自動地擴展純量以填滿所有需要的位置,然後執行指定的運算。

>> A(1,[1 3])=pi
A =
3.1416 2.0000 3.1416
0 0 0
7.0000 8.0000 9.0000

這是另一個例子,其中純量 被擴展以填滿二個位置。再思考一下函式reshape以純量作為輸入時會作些什麼。讓我們建立一個包含數字2的二列四行(2-by-4)的陣列。

>> D(2*4)=2 % 建立一個有8個元素的陣列
D =
0 0 0 0 0 0 0 2

>> D(:)=2 % 純量擴展
D =
2 2 2 2 2 2 2 2

>> D = reshape(D,2,4) % 重新塑型(reshape)
D =
2 2 2 2
2 2 2 2

第一行 D(2*4)=2 產生了長度為8的列向量,並且在最後的一行放置2。接著D(:)=2 使用純量擴展來用2填滿D中所有的元素。最後結果被重新塑型為想要的尺寸。

有時想要在向量和二維(2-D)陣列間執行一些數學運算.例如,考慮陣列:

>> A = reshape(1:12,3,4)&#039
A =
1 2 3
4 5 6
7 8 9
10 11 12
>> r=[3 2 1]
r =
3 2 1

假設我們希望從A的第i行減去r(i)。一個達成的方法是
>> Ar=[A(:,1)-r(1) A(:,2)-r(2) A(:,3)-r(3)]
Ar =
-2 0 2
1 3 5
4 6 8
7 9 11

另外可以使用索引法:
>> R=r([1 1 1 1],:) % 複製r成為四列
R =
3 2 1
3 2 1
3 2 1
3 2 1

>> Ar= A-R % 現在使用元素對元素的減法
Ar =
-2 0 2
1 3 5
4 6 8
7 9 11

陣列R也可使用更快且更一般性的計算,只要使用函式ones和size或使用函式repmat,這些函式在稍後會討論。考慮以下的例子。

>> R=r(ones(size(A,1),1) ,:) % 這是Tony的技巧(誰是Tony??)
R =
3 2 1
3 2 1
3 2 1
3 2 1

>> R=repmat(r,size(A,1),1) % 通常比Tony的技巧更快
R =
3 2 1
3 2 1
3 2 1
3 2 1

在上面的例子中,size(A,1)傳回A的列數。

有時候以單一個索引來使用陣列元素會更方便。當索引在MATLAB中被使用時,索引會從第一行來開始計算元素。

>> D=reshape(1:12,3,4) % 新資料
D =
1 4 7 10
2 5 8 11
3 6 9 12
>> D(2)
ans =
2
>> D(5)
ans =
5

>> D(end)
ans =
12
>> D(4:7)
ans =
4 5 6 7

MATLAB函式sub2ind和ind2sub執行運算來分別將從列和行的下標轉換到索引,及從索引轉換到列和行的下標,例如,

>> sub2ind(size(D),2,4)
ans =
11

>> [r,c]=ind2sub(size(D),11)
r =
2
c =
4

在第二列、第四行的元素是第11個元素。注意到這二個函式需要知道陣列的大小以便搜尋,也就是說,size(D),而非D本身。

除了根據陣列的下標來對陣列取址外,如果陣列的大小等於陣列被取址的大小,那麼也可以用邏輯陣列(logical arrays) ──邏輯運算的結果(稍後將討論地更透徹些)。在此例中,真實的(True,用1代表)元素被留下而偽的(False,用0代表)元素被乎略。例如,

>> x=-3:3 % 建置資料
x =
-3 -2 -1 0 1 2 3
>> abs(x)>1
ans =
1 1 0 0 0 1 1

傳回一個有1(True)的邏輯陣列,其中1代表x中絕對值大於1的位置,其它則以0(False)代表。邏輯表示式的章節將包含更詳細邏輯表示式的資訊。

>> y=x(abs(x)>1)
y =
-3 -2 2 3

取中絕對值大於1的值來建立y。

注意,即使abs(x)>1產生了陣列[1 1 0 0 0 1 1],它並不等於包含這些值的數值陣列;也就是說,

>> y=x([1 1 0 0 0 1 1 ])
??? Index into matrix is negative or zero. See release notes on changes to logical indices.

雖然abs(x)>1和[1 1 0 0 0 1 1]看來是一樣的向量,還是會有錯誤訊息。在第二個例子中,[1 1 0 0 0 1 1]是數值陣列而非邏輯陣列。結果導致MATLAB想要取出指定在[1 1 0 0 0 1 1]的元素,而產生了錯誤,因為並沒有元素0。理所當然地,MATLAB提供了了函式logical來將數值陣列轉換為邏輯陣列:
>> y=x( logical([1 1 0 0 0 1 1 ]) )
y =
-3 -2 2 3

再一次地,我們有了想要的答案。邏輯陣列在MATLAB中是另一種資料型態(data type)。直到現在,我們都只考慮數值陣列。總結如下:

用數值陣列指定陣列的下標會取出給定的數值索引的元素。另一方面,用邏輯陣列──由邏輯表示式傳回的結果,及函式logical來指定陣列下標,會取出邏輯值為True(1)的元素。

邏輯陣列在二維陣列上和在向量上時,作用得一樣好,例如:

>> B=[5 -3; 2 -4] % 新資料
B =
5 -3
2 -4

>> x=abs(B)>2 % 邏輯的結果
x =
1 1
0 1

>> y=B(x) % 取出為True的值
y =
5
-3
-4

然而,上面最後結果傳回的是行向量,因為沒有辦法在只有三個元素的情況下去定義二維陣列。無論取出多少個元素,MATLAB使用single-index的順序來取出所有為true的元素,然後形成或重塑結果成行向量。

上述陣列取址的技巧可被總合如下表。
陣列取址 描述
A(r,c) 取出在A中由想要的列構成的索引向量r和想要的行構成的索引向量c定義的子陣列。
A(r,:) 取出在A中由想要的列構成的索引向量r和所有的行定義的子陣列。
A(:,c) 取出在A中由所有的列和想要的行構成的索引向量c定義的子陣列。
A(:) 一行接一行地取出在A中所有的元素為一個行向量。如果A(:)出現在等號左邊,它代表在不改變A的形狀的情況下,用等號右邊的元素來填滿A。
A(k) 取出在A中由單索引向量k定義的子陣列,就好像A是行向量A(:)。
A(x) 取出在A中由邏輯陣列x定義的子陣列。必須和A同樣大小。

5.9 陣列排序

對於資料陣列在數值應用上有一常見工作:排序。在MATLAB中,函式sort執行此工作,例如
>> x=randperm(8) % 新資料
x =
8 2 7 4 3 6 5 1
>> xs=sort(x) % 將資料遞增排序
xs =
1 2 3 4 5 6 7 8
>> [xs,idx]=sort(x) % 排序後傳回排序前順序的索引(sort index)
xs =
1 2 3 4 5 6 7 8
idx =
8 2 5 4 7 6 3 1

如上所示,sort函式傳回一個或二個輸出。第一個是將輸入的引數遞增排序,而第二個則是排序前順序的索引(sort index),舉例說明,xs(k)=x(idx(k))。

注意到當MATLAB函式傳回二個或更多個變數時,它們在等號的左方用方括弧圍著。這與之前討論的陣列處理語法是不同的,在等號右方的[a,b]是用來建立『在a之後附加b』的新陣列。

如果需要遞減排序,輸出必須利用之前說過的索引的技巧來反轉 ,例如,
>> xsd=xs(end:-1:1)
xsd =
8 7 6 5 4 3 2 1
>> idxd=idx(end:-1:1)
idxd =
1 3 6 7 4 5 2 8

當二維陣列出現的時候,sort的作用則不同了,舉例說明,
>> A=[randperm(6);randperm(6);randperm(6);randperm(6)] % 新資料
A =
4 3 6 2 1 5
5 3 1 4 2 6
6 4 2 5 3 1
5 6 3 1 4 2

>> [As,idx]=sort(A)
As =
4 3 1 1 1 1
5 3 2 2 2 2
5 4 3 4 3 5
6 6 6 5 4 6
idx =
1 1 2 4 1 3
2 2 3 1 2 4
4 3 4 2 3 1
3 4 1 3 4 2
在此sort函式將每行與其它行獨立地遞增排序,且傳回的索引是每一行的。在許多案例中,我們更感興趣的是根據某一行去寺陣列作排序。在MATLAB中要作到很簡單,例如,

>> [tmp,idx]=sort(A(:,4)); % 只對第四行排序
>> As=A(idx,:) % 用idx來將每一行重排
As =
5 6 3 1 4 2
4 3 6 2 1 5
5 3 1 4 2 6
6 4 2 5 3 1
現在As的列是根據A的第四行重新排序過的列,其中As的第四行是遞增排序。
也可以去對每列排序而不只是上頭舉例的每一行,例如,
>> As=sort(A,2) % 用第二個維度來排序
As =
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6

>> As=sort(A,1) % 和sort(A)是一樣的
As =
4 3 1 1 1 1
5 3 2 2 2 2
5 4 3 4 3 5
6 6 6 5 4 6

藉由在sort中使用第二個引數,你可以指定要排序的方向。因為在A(r,c)中第一個出現的列的維度,sort(A,1)代表對列作排序。因為行的維度第二個出現,所以sort(,)代表對行作排序。
本章在資料分析上包含更多關於sort函式的資訊。

5.10 子陣列搜尋

許多時候需要知道陣列中滿足某些關係式的元素的索引或下標。在MATLAB中這件事可以由執行函式find來完成,find在關係式成立時(為True時)會傳回下標,例如,

>> x=-3:3
x =
-3 -2 -1 0 1 2 3
>> k=find(abs(x)>1) % 找到那些abs(x)>1元素的下標
k =
1 2 6 7
>> y=x(k) % 使用在k中的索引來建立y
y =
-3 -2 2 3
>> y=x(abs(x)>1) % 用邏輯取址(logical addressing)來建立相同的y向量
y =
-3 -2 2 3

函式find也可以在二維陣列上作用,例如,

>> A=[1 2 3; 4 5 6; 7 8 9] % 新資料
A =
1 2 3
4 5 6
7 8 9
>> [i,j]=find(A>5) % i和j在此並不再等於sqrt(-1)
i =
3
3
2
3
j =
1
2
3
3

在此放在i和j中排序過的索引分別是關係式判斷為True的列和行的索引。也就是說,A(i(1),j(1))是A中的第一個A>5的元素。

另外,find也可傳回二維陣列的單索引,例如,
>> k=find(A>5)
k =
3
6
8
9
這二種二維陣列的索引傳回方式中,後面這種單索引(single-index)型式通常更有用處,例如,

>> A(k) % 看大於5的元素
ans =
7
8
6
9

>> A(k)=0 % 將以k取址的元素設為0
A =
1 2 3
4 5 0
0 0 0

>> A=[1 2 3; 4 5 6; 7 8 9] % 回復資料
A =
1 2 3
4 5 6
7 8 9

>> A(i,j) % 這就是 A([3 3 2 3],[1 2 3 3])
ans =
7 8 9 9
7 8 9 9
4 5 6 6
7 8 9 9

>> A(i,j)=0 % 這也是A([3 3 2 3],[1 2 3 3])
A =
1 2 3
0 0 0
0 0 0

上面這個A(i,j)的例子並不能和之前單索引的例子一樣被瞭解透徹。將A(k) 假設等於A(i,j)是MATLAB在索引時常見的錯誤。上面的A(i,j)其實等於

>> [A(3,1) A(3,2) A(2,3) A(3,3)
A(3,1) A(3,2) A(2,3) A(3,3)
A(2,1) A(2,2) A(2,3) A(2,3)
A(3,1) A(3,2) A(2,3) A(3,3)]
ans =
7 8 6 9
7 8 6 9
4 5 6 6
7 8 6 9

在此,在i中的第一列索引會和所有在j中的行索引配對成為結果中的第一列。然後,在i中的第二列索引會和所有在j中的行索引配對成為結果中的第二列,…。根據這樣的型式,A(i,j)的對角元素等於A(k)中的元素。因此,如果使用A(i,j)的對角元素,則二種方法是相同的,
>> diag(A(i,j))
ans =
7
8
6
9

雖然diag(A(i,j))= A(k),不過A(k)比較好,因為它不會建立一個中間媒介的方陣。
同樣地,A(i,j)=0等價於
>> A(3,1)=0; A(3,2)=0; A(2,3)=0; A(3,3)=0; % i(1)和所有的j
>> A(3,1)=0; A(3,2)=0; A(2,3)=0; A(3,3)=0; % i(2)和所有的j
>> A(2,1)=0; A(2,2)=0; A(2,3)=0; A(2,3)=0; % i(3)和所有的j
>> A(3,1)=0; A(3,2)=0; A(2,3)=0; A(3,3)=0; % i(4)和所有的j
A =
1 2 3
0 0 0
0 0 0
根據上面的等價關係,很清楚地,一般在用find來作子陣列搜尋時,A(i,j)並不如 A(k)般好用。

以上的觀念可以整理成下表。
陣列搜尋 描述
i=find(x) 傳回陣列x中非零元素的單索引值
[r,c]=find(x) 傳回陣列x中非零元素的列和行索引

除了使用函式find來辨識在陣列中的特殊元素外,極大值和極小值和它們在陣列中的位置通常也很有用。MATLAB提供了max和min函式來達成這些工作。考慮下例。

>> v=rand(1,6) % 新資料
v =
0.7833 0.6808 0.4611 0.5678 0.7942 0.0592

>> max(v) % 傳回極大值
ans =
0.7942

>> [mx,i]=max(v) % 極大值和它的索引
mx =
0.7942
i =
5

>> min(v) % 傳回極小值
ans =
0.0592

>> [mn,i]=min(v) % 極小值和它的索引
mn =
0.0592
i =
6

對於二維陣列而言min和max的行為有些許差異,例如,

>> A=rand(4,6)
A =
0.6029 0.8744 0.9901 0.2140 0.7266 0.4399
0.0503 0.0150 0.7889 0.6435 0.4120 0.9334
0.4154 0.7680 0.4387 0.3200 0.7446 0.6833
0.3050 0.9708 0.4983 0.9601 0.2679 0.2126

>> [mx,r]=max(A)
mx =
0.6029 0.9708 0.9901 0.9601 0.7446 0.9334
r =
1 4 1 4 3 2

>> [mn,r]=min(A)
mn =
0.0503 0.0150 0.4387 0.2140 0.2679 0.2126
r =
2 2 3 1 4 4

上面的mx是在A的每一行中包含極大值的向量,而r是極大值出現的列索引。同樣的原則用於函式min的mn和r。要找到在2維陣列中全面性的(真正的)極大值或極小值,你可以採用二種作法:

>> mmx = max(mx) % 再用一次max於之前的結果
mmx =
0.9901
>> [mmx,i] = max(A(:)) % 首先將A重新塑型成行向量
mmx =
0.9901
i =
9

上面的第一行基本上就是max(max(A)),需要二次函式呼叫。在很多情況下較偏愛第二個命令,因為它也傳回極大值發生處的單索引,也就是,mmx=A(i)。後面這個方法在多維度陣列時也同樣有用,我們將在下章中討論。
當陣列有複數個極小值或極大值時,min和max傳回的索引是第一個極值發生處。要找出所有的極大和極小值需要使用find函式,舉例來說,
>> x=[ 1 4 6 3 2 1 6]
x =
1 4 6 3 2 1 6
>> mx=max(x)
mx =
6
>> i=find(x==mx) %索引代表等於mx的值
i =
3 7

本章在資料分析上包含更多關於min和max函式的資訊。

5.11 陣列處理函式

除了在之前章節中描述過的隨意的陣列取址和處理能力之外,MATLAB提供了數個常見的陣列處理函式。這些處理中有很多個很容易實行,例如:

>> A=[ 1 2 3; 4 5 6; 7 8 9] % 更新資料
A =
1 2 3
4 5 6
7 8 9
>> flipud(A) % 將陣列以上下方向翻轉
ans =
7 8 9
4 5 6
1 2 3
>> fliplr(A) % 將陣列以左右方向翻轉
ans =
3 2 1
6 5 4
9 8 7
>> rot90(A) % 將陣列逆時針方向旋轉90度
ans =
3 6 9
2 5 8
1 4 7
>> rot90(A,2) % 將陣列逆時針方向旋轉2*90度
ans =
9 8 7
6 5 4
3 2 1

>> B=1:12 % 更多的資料
B =
1 2 3 4 5 6 7 8 9 10 11 12
>> reshape(B,2,6) %重新塑型成二列、六行,一行一行來填滿
ans =
1 3 5 7 9 11
2 4 6 8 10 12
>> reshape(B,[2,6]) % 和上一個命令相同
ans =
1 3 5 7 9 11
2 4 6 8 10 12
>> reshape(B,3,4) %重新塑型成三列、四行,一行一行來填滿
ans =
1 4 7 10
2 5 8 11
3 6 9 12

>> reshape(A,3,2) % A有超過32個元素,喔~槽糕!
??? Error using ==> reshape
To RESHAPE the number of elements must not change.

>> reshape(A,1,9) % 將A拉伸成為一個列向量
ans =
1 4 7 2 5 8 3 6 9

以下的函式將一個陣列的一部份取出來構成另一個陣列。
>> A % 想起A是什麼
A =
1 2 3
4 5 6
7 8 9
>> diag(A) % 用diag取出對角線上的元素
ans =
1
5
9
>> diag(ans) % 記得這個嗎?同樣的函式,不同的行為
ans =
1 0 0
0 5 0
0 0 9
>> triu(A) % 取出上三角的部份
ans =
1 2 3
0 5 6
0 0 9
>> tril(A) % 取出下三角的部份
ans =
1 0 0
4 5 0
7 8 9
>> tril(A)-diag(diag(A)) % 不含對角線的下三角矩陣的部份
ans =
0 0 0
4 0 0
7 8 0

以下的函式從其它的陣列中來建立陣列。
>> a=[1 2;3 4] % 一個較小的資料陣列
a =
1 2
3 4

>> b=[0 1; -1 0] % 另一個較小的資料陣列
b =
0 1
-1 0

>> kron(a,b) % a和b 的kronecker tensor product
ans =
0 1 0 2
-1 0 -2 0
0 3 0 4
-3 0 -4 0
以上的kron(a,b)等於
>> [1*b 2*b
3*b 4*b]
ans =
0 1 0 2
-1 0 -2 0
0 3 0 4
-3 0 -4 0

>> kron(b,a) % b和a 的kronecker tensor product
ans =
0 0 1 2
0 0 3 4
-1 -2 0 0
-3 -4 0 0
以上的kron(b,a)等於
>> [0*a 1*a
-1*a 0*a]
ans =
0 0 1 2
0 0 3 4
-1 -2 0 0
-3 -4 0 0

所以kron(a,b)會將第一個引數的每個元素取出並且將它乘以第二個引數,然後建立一個區塊陣列(block array)。
最有用的陣列處理函式是repmat,之前已經介紹過了。

>> a %叫回資料
a =
1 2
3 4
>> repmat(a,1,3) % 向下複製a一次,將結果再向右複製三次
ans =
1 2 1 2 1 2
3 4 3 4 3 4
>> repmat(a,[1,3]) %和上面一樣
ans =
1 2 1 2 1 2
3 4 3 4 3 4
>> [a a a] %和上面一樣
ans =
1 2 1 2 1 2
3 4 3 4 3 4
>> repmat(a,2,2) % 向下複製a二次,將結果再向右複製二次
ans =
1 2 1 2
3 4 3 4
1 2 1 2
3 4 3 4
>> repmat(a,2) %和上面一樣
ans =
1 2 1 2
3 4 3 4
1 2 1 2
3 4 3 4
>> [ a a ; a a] %和上面一樣
ans =
1 2 1 2
3 4 3 4
1 2 1 2
3 4 3 4

和上面及之前舉過的例子一樣,函式repmat和reshape以二個方式來看待『索引的引數』。『索引的引數』可以由各別的輸入引數傳遞(例如repmat(a,1,3)),或可由在一個向量引數中的個別元素傳遞(也就是repmat(a,[1,3])這種型式)。此外,對於repmat,如果只有一個第二項輸入引數時repmat(A,n),則會被解釋為repmat(A,[n n])的意思。

最後,要將一個純量複製成和另一個陣列同樣大小的陣列,你可以簡單地使用repmat(d,size(A)),其中函式size將在下節中討論。舉例說明,

>> A=reshape(1:12,[3 4]) %新資料
A =
1 4 7 10
2 5 8 11
3 6 9 12

repmat(pi,size(A)) % 將pi複製成和A同樣大小的陣列
ans =
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416
3.1416 3.1416 3.1416 3.1416

5.12 陣

—–
PING:
TITLE: Matlab – about Matrix
URL: http://www.wretch.cc/blog/Lak4CYUT&article_id=3500914
IP: 127.0.0.1
BLOG NAME: 【天使爬上惡魔的床】
DATE: 01/03/06 01:47:00 PM
在網路上發現一位 matlab 超級達人,
也感謝他翻釋的文件,讓我在做 Project 時有相當充足的資料。

今天在寫 Matlab 程式,
發現在做 Matrix 的操作時,
—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第四章 中譯

第4章 Script M-files

對於簡單的問題,在Command window中的MATLAB提示符號之後鍵入你的需求是又快又有效的方法。然而,當命令數增加或你希望改變一個或多個變數的值,並且重新執行一些命令時,在提示符號後快速地鍵入MATLAB命令變成了一件冗長乏味的事。MATLAB針對此問題,提供了一合理的解法。它允許你將一些MATLAB命令放置在一文字檔之中,然後告訴MATLAB開啟此檔並且執行裡頭的命令,就如同你在提示符號後鍵入這些命令一樣。這些檔案被稱作script files或簡稱M-files。術語script象徵MATLAB輕鬆地從檔案中讀入script。術語M-file讓人認清script 檔案名稱必須以附加檔名’.m’作為結束的事實,例如,example1.m。

4.1 使用SCRIPT M-FILE
要建立一個script M-file, 在MATLAB desktop toolbar(工具列上)按下blank page icon(空白頁圖示)或是從File選單中選擇New並且選擇M-file。這麼做會將文字編輯視窗帶出,而你可以在文字編輯視窗內鍵入MATLAB命令。以下的script M-file是之前考慮過的例子中的命令:

%script M-file example1.m

erasers=4; %每個物品的數目
pads = 6;
tape = 2;
items = erasers + pads +tape
cost = erasers*25+pads*52 + tape*99
average_cost = cost / items

這個檔可以藉由點選在Editor視窗中toolbar(工具列)上的Run圖示或是按下F5功能鍵而被存到磁碟裡且立刻執行。另外,你也可以選擇File選單中的Save選項來將這個檔案儲存成M-file example1.m;然後只要在MATLAB提示符號後鍵入script檔名(不需要.m的附加檔名)就可以執行了:

>>example1
items=
12
cost =
610
average_cost =
50.833

當MATLAB解譯(直譯)上述在example1的程式碼時,它遵守著前一章中提到的階級順序(hierarchy)。簡而言之,MATLAB授與「目前的變數」及「內建的命令」較「M-file名稱」高的優先權。也就是說, 如果example1不是目前的MATLAB變數或內建的MATLAB命令(它確實不是),那麼MATLAB會開啟example1.m的檔案(如果它找得到的話),並且執行檔案內的命令就如同在Command window的提示符號之後鍵入這些命令一樣。結果是,在-file內的命令會去存取所有在MATLAB workspace中的變數,而所有由-file建立的變數也會成為workspace之中的變數。一般來說,那些由-file讀入的命令當它們被執行時,並不會被顯示出來。echo on命令則告訴MATLAB當命令被讀入然後執行時,要顯示或回應命令到Command window中。你可能可以猜到echo off命令的作用了。echo命令本身會觸發(toggle)MATLAB到echo(有回應) 的狀態。

建立script M–file的能力使得回答「若是…又怎麼樣? (“what if?”)」問題變得十分簡單。舉例來說,你可以重覆開啟example. 這個M-file,改變erasers, pads, tape的數目,然後按下F5鍵來儲存並且執行這個檔案。這項能力的威力不能被說得太誇張。而藉由建立M-file,你的命令被儲存到磁碟中以備往後使用。

當你使用script file時,譬如在example1.m中,MATLAB命令的效用就已十分顯著。命令允許你將在M-file裡的程式碼加上說明文件,這可讓你在以後重看程式碼時不會忘記。此外,使用分號在每行程式的尾端會抑制結果的顯示,這可使你控制script file的輸出,於是只有重要的結果會被顯示。因為script file的功用,MATLAB提供數種當你使用M-file時特別好用的函式:

函式 函式描述
beep 使電腦發出嗶嗶聲
disp(variable name) 在不指出變數名稱的情況下顯示結果
echo 當它們被執行時,會控制Command window回應script file的內容與否
input 提示使用者要輸入
keyboard 暫時將控制權交予鍵盤。按下return六個英文字母則會將控制權交回給script M-file。
pause of pause(n) Pause是暫停直到使用者按下鍵盤上的任一鍵,而pausen則是暫停n秒後再繼續。
waitforbuttonpress 暫停直到使用者按下滑鼠鍵或是鍵盤上的按鍵

當一個MATLAB命令未以分號終結時,命令的結果會被顯示在Command window中並且會指出變數的名稱。若要較美觀的結果顯示,通常不顯示其變數名稱是較容易的方案。在MATLAB中,可以命令display來達成,例如:

>>items
items=
12
>>display(items)
12

當你需要計算許多個案例時,你不需要重覆地編輯script file,input 命令讓你在script file執行時可以在提示符號後面輸入你要的值。例如,考慮修改過的example1.m script file:

% script M-file example1.m

erasers = 4; %每樣物品的個數
pads = 6;
tape = input(&#039Enter the number of rolls of tape purchased > &#039);
items = erasers + pads + tape
cost = erasers *25 + pads*52 + tape*99
average_cost = cost / items

執行此script M-file會產生
>> example1
Enter the number of rolls of tape purchased > 3
items =
13
cost =
709
average_cost =
54.5385

我們鍵入數字3共且按下Return(或Enter)鍵來回應提示符號。其它剩下的命令則和之前一樣被執行。函數input可接受任何有效的MATLAB表示法來作為輸入。舉例說明:再次執行script file,並且給予有效但不同的輸入

>> example1
Enter the number of rolls of tape purchased > round(sqrt(13))-1
items =
13
cost =
709
average_cost =
54.5385

在上例中,錄音帶(tape)的捲數被設為表示式round(sqrt(13))-1計算後的結果。
為了見識到echo命令的效果,在script file中加上它並且執行:

% script M-file example1.m
echo on
erasers = 4; %每樣物品的個數
pads = 6;
tape = input(&#039Enter the number of rolls of tape purchased > &#039);
items = erasers + pads + tape
cost = erasers *25 + pads*52 + tape*99
average_cost = cost / items
echo off

>> example1
erasers = 4; %每樣物品的個數
pads = 6;
tape = input(&#039Enter the number of rolls of tape purchased > &#039);
Enter the number of rolls of tape purchased > 2
items = erasers + pads + tape

items =
12
cost = erasers *25 + pads*52 + tape*99
cost =
610
average_cost = cost / items
average_cost =
50.8333
echo off

就如同你從此例子中看到的,echo命令使得結果難以閱讀。不過,就另外一方面來說,當你在替更複雜的script file除錯時,此時echo命令就是非常有幫助了。

4.2啟動和結束
當MATLAB啟動時,它會執行二個script M-file,分別是matlabrc.m和startup.m。matlabrc.m是伴隨著MATLAB的,而且在一般狀況下它不應該被修改。在此M-file中的命令是用來設定預設Figure window的尺寸大小和放置位置及一些其它預設的性質。而MATLAB預設的搜尋路徑是由matlabrc.m中呼叫pathdef.m來加以設定。Path Browser(路徑瀏覽器)及一些在Command window內使用來編輯路徑的函式會負責維謢pathdef.m檔,所以你不需要用文字編輯器來編輯此檔。
在matlabrc.m中的命令會檢查startup.m是否存在於MATLAB的搜尋路徑中。如果它存在,則會執行startup.m內的命令。這個可有可無的M-file一般包含著用來增加個人化預設值的命令。舉例來說,一般會在startupm中放置一個或數個addpath或是path命令,以便增加額外的目錄到搜尋路徑裡。同樣地,也可以改變預設的數值顯示格式,例如,format compact。如果你有灰階單色(grayscale)螢幕,那麼命令graymon對設定預設灰階圖形特徵是是很有用處的。更甚者,如果你想要繪製具有不同預設值的圖形, colordef的呼叫可能會在startup.m中出現。因為startup.m是一標準的script M-file,對於裡面能放置什麼樣的命令並沒有限制。不過,在startup.m裡頭放置quit命令可能是不智的!在單一使用者環境安裝時,startup.m一般會儲存在MATLAB路徑中的toolbox/local子目錄中。若是在網路安裝時,在你啟動MATLAB時的預設目錄下放置startup.m檔可能是個較方便的方法。

當你由MATLAB desktop window中的File選單中的Exit MATLAB選項或是在MATLAB提示符號後鍵入exit或quit來結束MATLAB時,MATLAB會搜尋MATLAB路徑中,看看有沒有一個叫做finish.m的M-file檔。如果找得到這個檔,那麼會在MATLAB結束前執行在finish.m中的命令。例如,以下的finish.m檔會在利用一個對話框來提示使用者在離開前確認是否要離開。命令quit cancel提供了一個取消離開的方法。

% FINISH 確認離開MATLAB的意願
question= &#039Are You Sure You Want To Quit?&#039
button=questdlg( question, &#039Exit Request&#039, &#039Yes&#039, &#039No&#039, &#039No&#039 )
%譯註:上頭questdlg內的最後一個參數是預設值,故重覆了二個&#039No&#039
switch button
case &#039No&#039
quit cancel; % 如何取消離開!
end
% &#039Yes&#039 則會令MATLAB結束

—–

24 十二月, 2004 Posted by | 精通Matlab 6 | 發表留言

精通Matlab 6 第三章 中譯

3 MATLAB 桌面

如前章所述,當你執行MATLAB時,會在你的電腦螢幕上產生一到多個視窗。這些視窗中有一個標題為MATLAB的,被叫做是MATLAB desktop。這個視窗既包含且管理MATLAB中的其它視窗。根據你設定MATLAB的方式,這些視窗中有一些和desktop視窗相關的可能會看不見,而有些可能會不「歸屬」在MATLAB視窗中。這「歸屬」的動作我們稱之為停駐(docked)。在本書中並不討論如何管理MATLAB desktop視窗和其相關視窗。如果你熟悉其它以視窗為本的程式,那麼處理在MATLAB中的視窗則顯得相當簡單了。MATLAB desktop的選單項目(menu items)會根據哪個視窗正在作用而隨之改變。此外,有許奓有用的contextual menus(藉由在一個item上按下滑鼠右鍵而加以使用)。如果你不熟悉以視窗為本的程式,它可能是從其它資源尋找一般輔助的最有效的方法。不論用什麼方法,找出哪個視窗和desktop相關,檢視在MATLAB desktop視窗裡的View選單下的items。

MATLAB使用的視窗包含有(1)指令(command),(2)指令的歷史記錄(command history),(3)啟用板???(Launch Pad),(4)目前的目錄(的瀏覽器),(5)輔助說明(的瀏覽器),(6)Workspace(的瀏覽器),(7)陣列編輯器(array editor)。下表是每個視窗用途的概觀:

MATLAB Desktop 視窗
視窗名 視窗描述
指令 管理MATLAB要處理的指令
指令的歷史記錄 之前執行過的指令在此視窗中出現
Launch Pad 將要使用的工具、展示程式和技術文件樹狀排列
目前的目錄 目錄和檔案操控的GUI
輔助說明 尋找和觀看線上文件的GUI
Workspace 觀察、讀取和寫入MATLAB變數的GUI
陣列編輯器 修改MATLAB變數內容的GUI
編輯器/除錯器 MATLAB文字檔的文字編輯器和除錯器

3.2 管理MATLAB WORKSPACE

在MATLAB desktop內所有視窗執行的動作,在command window內都有支援。本章剩餘的部分將對Command window多所著墨。

在Command window裡所建構的資料和變數存在在一個叫作MATLAB workspace或叫作Base workspace的地方。使用命令who除了可以看見在Workspace視窗中的變數外,也可以看到在MATLAB workspace中變數的名稱。

>> who

Your variables are:

angle_c1 c4 cost pads
ans c5 deg_c1 real_c1
average_cost c6 erasers tape
c1 c6i imag_c1
c2 c6r items
c3 check_it_out mag_c1

你所見到的變數可能會和上頭的不一樣,它們會根據你從啟動MATLAB起要求MATLAB作了什麼事而有所不同。若要若詳細的資訊,使用命令whos:

>> whos
Name Size Bytes Class

angle_c1 1×1 8 double array
ans 1×1 8 double array
average_cost 1×1 8 double array
c1 1×1 16 double array (complex)
c2 1×1 16 double array (complex)
c3 1×1 16 double array (complex)
c4 1×1 16 double array (complex)
c5 1×1 16 double array (complex)
c6 1×1 16 double array (complex)
c6i 1×1 8 double array
c6r 1×1 8 double array
check_it_out 1×1 8 double array
cost 1×1 8 double array
deg_c1 1×1 8 double array
erasers 1×1 8 double array
imag_c1 1×1 8 double array
items 1×1 8 double array
mag_c1 1×1 8 double array
pads 1×1 8 double array
real_c1 1×1 8 double array
tape 1×1 8 double array

Grand total is 21 elements using 216 bytes

在此,每個變數都列出了它的size、使用的byte數、和它的class。因為MATLAB是陣列導向(array-oriented),即使所有以上的變數都是純量,所有變數還是屬於雙精度陣列的class。稍後,當其它的資料型別或是class引入時,最後一行將會提供更多有用的資訊。上面所列出的也會在Workspace window中顯示出來,你可在MATLAB提示符號後打上命令workspace,或是在MATLAB desktop的View選單上選擇Workspace來看到workspace window。

命令clear會從MATLAB workspace中刪除變數。舉例來說,

>> clear real_c1 imag_c1 c*
>> who

Your variables are:

angle_c1 deg_c1 mag_c1
ans erasers pads
average_cost items tape

刪除了變數real_c1,imag_c1和所由以字母c作為開頭的變數。Clear函式的其它選項,可以使用命令help或helpwin來找到相關資訊,舉例來說:

>> help clear

CLEAR Clear variables and functions from memory.
CLEAR removes all variables from the workspace.
CLEAR VARIABLES does the same thing.
CLEAR GLOBAL removes all global variables.
CLEAR FUNCTIONS removes all compiled M- and MEX-functions.

CLEAR ALL removes all variables, globals, functions and MEX links.
CLEAR ALL at the command prompt also removes the Java packages
import list.

CLEAR IMPORT removes the Java packages import list at the command
prompt. It cannot be used in a function.

CLEAR CLASSES is the same as CLEAR ALL except that class definitions
are also cleared. If any objects exist outside the workspace (say in
userdata or persistent in a locked m-file) a warning will be issued
and the class definition will not be cleared. CLEAR CLASSES must be
used if the number or names of fields in a class are changed.

CLEAR VAR1 VAR2 … clears the variables specified. The wildcard
character &#039*&#039 can be used to clear variables that match a pattern.
For instance, CLEAR X* clears all the variables in the current
workspace that start with X.

If X is global, CLEAR X removes X from the current workspace,
but leaves it accessible to any functions declaring it global.
CLEAR GLOBAL X completely removes the global variable X.

CLEAR FUN clears the function specified. If FUN has been locked
by MLOCK it will remain in memory. Use a partial path (see
PARTIALPATH) to distinguish between different overloaded versions of
FUN. For instance, &#039clear inline/display&#039 clears only the INLINE
method for DISPLAY, leaving any other implementations in memory.

CLEAR ALL, CLEAR FUN, or CLEAR FUNCTIONS also have the side effect of
removing debugging breakpoints and reinitializing persistent variables
since the breakpoints for a function and persistent variables are
cleared whenever the m-file changes or is cleared.

Use the functional form of CLEAR, such as CLEAR(&#039name&#039),
when the variable name or function name is stored in a string.

See also WHO, WHOS, MLOCK, MUNLOCK, PERSISTENT.

顯然地,clear命令不僅是刪除變數。在你更熟稔MATLAB的其它特性時,你會發現它的其它用途。

3.3記憶體管理
MATLAB在建立變數和使用M-file函式時,會分配記憶體給變數。根據你用的電腦,MATLAB可能會執行到用盡記憶體──使得MATLAB再也無法執行任何工作。當你使用clear命令來刪除變數時,MATLAB根據被清除的變數多寡會釋放相當的記憶體。然而,如此過了一段時間之後,記憶體可能會變成片段的(fragmented),也就是MATLAB的記憶體空間是由許多小的空白記憶體片段所產生的。因為MATLAB總是將變數儲存在連續chunk的記憶體中,這些空白的記憶體片段可能會無法再被使用。為了減輕這個問題, pack命令會執行記憶體資源回收(memory garbage collection)。這個命令會將所有在MATLAB workspace中的變數儲存到磁碟上,從workspace清除所有的變數,然後再reload(重新讀回)所有的變數到workspace裡。結束時,所有的空白記憶體片段將會被合併成一個大的、可用的區塊(block)。你是否需要使用pack命令將根據你從電腦裡分配給MATLAB多少的記憶體?你已經在特定的節區(session)中執行了多久?及你建立了多少個變數?

3.4 格式化數值顯示
當MATLAB顯示數值的結果時,它遵守幾條規則。預設是:如果結果是整數,那麼MATLAB會以整數顯示它。同樣的,當結果是實數,MATLAB會以大約以小數點後4位小數來顯示它。如果結果中有很大的數字超過了這個範圍,MATLAB會將結果以類似科學記算機的科學符號來表示它。你可以在File選單中的preference選單項目中的Command window preferences(命令視窗偏好)中指定不同的數值格式,或是在提示符號後打上適當的MATLAB format命令來覆寫(override)這個預設行為。以特殊變數pi為例,以不同的format選項產生的數值顯示格式如下:

MATLAB命令 pi 註解
format short 3.1416 5位的數字
format long 3.14159265358979 15位的數字
format short e 3.1416e+000 5位的數字加上指數
format long e 3.141592653589793e+000 15位的數字加上指數
format short g 3.1416 以format short或format short e來佳最表示
format long g 3.14159265358979 以format long或format long e來佳最表示
format hex 400921fb54442d18 16進位的浮點數
format bank 3.14 小數點後取2位
format + + 正(+),負(-),或是零(0)
format rat 355/113 近似的有理數
format debug Structure address = 2937df8 m = 1 n = 1pr = 1b238c08 pi = 0 3.1416 除了short g外,內部儲存的資訊

注意:當你選擇不同的顯示格式時,MATLAB並不會改變一個數在內部的表示法;只有改變顯示出的格式罷了。所有的計算都以雙精度來執行算術運算。

3.5保有一個期間的記錄
有時候保有MATLAB一段期間中所有執行過的工作記錄是很有用的。Command History window 依時間前後排列,保有著從過去到現在MATLAB工作期間執行過的命令和函式的記錄,不過並不包括執行的結果。MATLAB提供了一個命令diary,這個命令能儲存所有Command window的活動到目前目錄中的一個文字檔裡。關於diary的輔助說明描述如下:

>> help diary

DIARY Save text of MATLAB session.
DIARY filename causes a copy of all subsequent command window input
and most of the resulting command window output to be appended to the
named file. If no file is specified, the file &#039diary&#039 is used.

DIARY OFF suspends it.
DIARY ON turns it back on.
DIARY, by itself, toggles the diary state.

Use the functional form of DIARY, such as DIARY(&#039file&#039),
when the file name is stored in a string.

3.6系統資訊
MATLAB提供了許多可以提供關於所使用的電腦和MATLAB版本資訊的命令。命令computer會傳回一個用來指出所用電腦的字串,例如:

>> computer
ans =
PCWIN

在這例子中,所用的電腦的作業系統是Windows 98。命令version傳回的字元字串會指出MATLAB的版本,例如:
>> version
ans =
6.0.0.51483 (R12)

而命令ver傳回MATLAB相關資訊和安裝好的工具箱(toolbox),例如:
>> ver
————————————————–
MATLAB Version 6.0.0.51483 (R12) on PCWIN
MATLAB License Number: 0
————————————————–
MATLAB Toolbox Version 6.0 (R12) 06-Oct-2000
Simulink Version 4.0 (R12) 16-Jun-2000
Control System Toolbox Version 5.0 (R12) 01-Sep-2000
Optimization Toolbox Version 2.1 (R12) 07-Jun-2000
Signal Processing Toolbox Version 5.0 (R12) 01-Jun-2000
Symbolic Math Toolbox Version 2.1.2 (R12) 11-Sep-2000

MATLAB授權資訊可以使用命令license和hostid來得到,例如:
> hostid
&#039

>> license
ans =
51483

當然囉,你輸入這些命令的結果會和上頭的結果不同,因為你的電腦和MATLAB版本都和用來產生以上結果的不同。

3.7 MATLAB搜尋路徑

MATLAB使用路徑搜尋(search path)來找出在磁碟中儲存檔案的資訊。MATLAB將檔案組織成許多的目錄和子目錄。

會找到MATLAB檔案的所有目錄的列表稱作是MATLAB搜尋路徑或簡稱MATLABPATH。

MATLAB路徑搜尋的方式如下:當你鍵入cow在MATLAB提示符號後,也就是,>>cow,MATLAB會做以下的事:

1. 它檢查是否在MATLAB workspace中有叫作cow的變數;如果沒有,
2. 它檢查是否cow是一個內建函式;如果不是,
3. 它檢查是否在目前的目錄中有一個檔名為cow.m;如果沒有,
4. 它檢查cow.m是否存在於MATLAB搜尋路徑中的某一處,它會根據已指定的順序來搜尋。
5. 如果這時還是沒有找到cow,那麼MATLAB會回報有錯誤(error)。

MATLAB會根據以上的搜尋策略來行動。如果cow是個變數,MATLAB會使用它。如果它是個內建函式,MATLAB會呼叫這個函式。如果cow.m是個在目前的目錄或者是在MATLAB搜尋路徑的某個地方的檔案,那麼會開啟cow.m這個檔並且根據檔案的內容來作用(行動)。在第4和11章裡已記載著,MATLAB有二種最常用的基本檔案型式;兩種都是內含MATLAB命令的文字檔。如需關於這些M-files更多的資訊,請參見第4和11章。

實際上,因為MATLAB一些先進的特性,MATLAB搜尋的程序比以上所描述的更加複雜。然而,以上的搜尋程序在大多數情況下已足以應付大部份MATLAB的工作了。關於MATLAB搜尋路徑更詳細的資訊可以在第11章中找到。

當MATLAB啟動時,MATLAB定義了預設的搜尋路徑,並將其指向所有MATLAB儲存檔案的目錄。這個搜尋路徑可以以數種方式顯示及修改。最簡單的方式就是利用Path Browser,Path Browser是一個用來檢視及修改MATLAB搜尋路徑的圖形使用者介面。Path Browser可以藉由從MATLAB desktop window中的File選單中選取Set Path…而加以使用。由於MATLAB的搜尋路徑總是指向MATLAB儲存檔案的所有目錄,而存取Path Browser的主要的目的是增加包含MATLAB檔的目錄到搜尋路徑中。

要在Command window裡顯示MATLAB的搜尋路徑,MATLAB提供函式matlabpath。此外,PathBrowser的特性能夠以函式path,addpath和rmpath在Command window中被複製。若需更多關於這些函式的資訊,請見線上文件。

24 十二月, 2004 Posted by | 精通Matlab 6 | 5 則迴響