10/31/2006

串接指令之應用

MATLAB Catenation Commands

串接兩矩陣,構成新矩陣之指令如下表:








函數名稱說明
cat沿設定方向串接
horzcat沿水平方向串接
vertcat沿垂直方向串接
repmat依垂直與水平方向倍數串接
blkdiag由現存之矩陣產生對角矩陣


下面為執行這些函數指令之例子:

串接矩陣與陣列



除使用中括號[]作簡單串接外,其他串接指令有cat、horzcat及vertcat等三個函數。這些指令可以交互運用,例如要將AB兩矩陣作垂向串接時,下述三個指令均可得到同樣的結果:

水平串接:

 C = [A B] %使用中括號,相隔用分號。
 C = cat(2, A, B); % 第一參數設定為2。
 C = horzcat(A, B); % 無額外參數。


垂直串接:

 C = [A; B] %使用中括號,相隔用分號。
 C = cat(1, A, B); % 第一參數設定為1。
 C = vertcat(A, B); % 無額外參數。


拷貝串接



使用repmat函數在垂向及水平方向產生不同數量之拷貝矩陣,其指令型式如下:

repmat(M, v, h)

MATLAB 將輸入矩陣垂直方向拷貝v 次;水平方向拷貝h次。下面舉例:


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

B = repmat(A, 2, 4)
B =
8 1 6 8 1 6 8 1 6 8 1 6
3 5 7 3 5 7 3 5 7 3 5 7
4 9 2 4 9 2 4 9 2 4 9 2
8 1 6 8 1 6 8 1 6 8 1 6
3 5 7 3 5 7 3 5 7 3 5 7
4 9 2 4 9 2 4 9 2 4 9 2


區塊對角矩陣



利用blkdiag函數可以結合矩陣,鉗入對角方向,產生許多區塊對角矩陣,在區塊之外的新建元素位置則設定為零:


A = magic(3);
B = [-5 -6 -9; -4 -4 -2];
C = eye(2) * 8;

D = blkdiag(A, B, C)
D =
8 1 6 0 0 0 0 0
3 5 7 0 0 0 0 0
4 9 2 0 0 0 0 0
0 0 0 -5 -6 -9 0 0
0 0 0 -4 -4 -2 0 0
0 0 0 0 0 0 8 0
0 0 0 0 0 0 0 8

如何擴張矩陣

How to expand the size of a Matrix

擴張矩陣有兩種方式:

  1. 增加新元素於一矩陣上。
  2. 儲存一元素於矩陣的範圍之外。


兩矩陣之結合


第一種情況是利用中括號[ ]。這個符號不僅作為產生新矩陣之方法,也可用來增加新元件或新陣列,只是當要要增加新元素或部份矩陣於一舊矩陣上時,必須先確定其大小是否合適。下面為其例:

A = ones(2, 5) * 6; % 2-by-5 matrix of 6's
B = rand(3, 5); % 3-by-5 matrix of random values

C = [A; B] % Vertically concatenate A and B
C =
6.0000 6.0000 6.0000 6.0000 6.0000
6.0000 6.0000 6.0000 6.0000 6.0000
0.9501 0.4860 0.4565 0.4447 0.9218
0.2311 0.8913 0.0185 0.6154 0.7382
0.6068 0.7621 0.8214 0.7919 0.1763



由此可知,矩陣往下延伸時,其行數必須相同。同理,若往右或左向延伸,其列數必須相同。

>>c=[];for k=1:4, c=[c;eye(3)*k];end;
>>c=
1 0 0
0 1 0
0 0 1
2 0 0
0 2 0
0 0 2
3 0 0
0 3 0
0 0 3
4 0 0
0 4 0
0 0 4


結構陣列之結合


結構陣列亦可利用矩陣增列的方式建立。建立之後再利用reshape指令進行重整。

%Concatenating to a Structure
% Create a 3X4 structure array M
for k=1:12
M(k)=struct('Name',{['code', num2str(k)]},'value',10*k+8);
end
M=reshape(M,3,4)
%Create a 3X2 array using the same field name
for kk=1:6
N(kk)=struct('Name',{['code', num2str(kk+12)]},'value',10*kk+2);
end
N=reshape(N,3,2)
%Concalenate N onto M alogn the horizontal dimension
S=[M N]
%-------------------------------------------


上面之程式經執行之後,會顯現結果如下:

>> S

S =

3x6 struct array with fields:
Name
value


原來的欄位為Name與value,利用相同的欄位可以增加同型式之結構矩陣。

小陣列結合大陣列


要將小陣列加入大陣列,其大小顯然不對等,但此時亦可指明置於大陣列中之位置,此位置可以超出大陣列之範圍,因而擴大其領域。大陣列之大小會配合增加,其餘未增加之空位以零補充,以維持其長方形矩陣之型式。

例如,一個 3X5 之矩陣之內容如下:


A = [ 10 20 30 40 50; ...
60 70 80 90 100; ...
110 120 130 140 150];


今若隨便增加一個新元素,以下面的操作方式,會產生錯誤的信息:

>>A = [A; 160]

??? Error using ==> vertcat
All rows in the bracketed expression must have the same
number of columns.


但若直接指定這一個元素置於某特定位置,如第四列第一行時,反而可行,其餘空間會自動以零補足。


A(4,1) = 160
A =
10 20 30 40 50
60 70 80 90 100
110 120 130 140 150
160 0 0 0 0


即使插入的是一組小陣列,只要指定於適當的位置,一樣可行,不會發生錯誤。


A(4:6,1:3) = magic(3)+300
A =
10 20 30 40 50
60 70 80 90 100
110 120 130 140 150
308 301 306 0 0
303 305 307 0 0
304 309 302 0 0



即使增加的新元素離開原矩陣的範圍甚遠,MATLAB一樣會將其他未觸及的部份補足零,以維持一個長方型矩陣:


A(4,8) = 300
A =
10 20 30 40 50 0 0 0
60 70 80 90 100 0 0 0
110 120 130 140 150 0 0 0
0 0 0 0 0 0 0 300


擴充結構陣列或細胞陣列


即使是結構陣列或細胞陣列亦可利用同一方法進行擴充。下面的例子是以儲存一額外細胞於原陣列之範圍之外的情形,同樣,MATLAB會將其他未指定的部份均填以空細胞[],以維持長方矩陣之外型:

設原來陣列為2X3大小:

C = {'Madison', 'G', [5 28 1967]; ...
46, '325 Maple Dr', 3015.28}


此時若增加一新細胞於C{3,1}之位置,則MATLAB 會增加一整列:


C{3, 1} = ...
struct('Fund_A', .45, 'Fund_E', .35, 'Fund_G', 20);
C =
'Madison' 'G' [1x3 double]
[ 46] '325 Maple Dr' [3.0153e+003]
[1x1 struct] [] []


擴充文字陣列


文字陣列以單一文字為元素,其擴充方式實際上與一般陣列相同,只是這種擴充方式並不理想,故也不建議使用這種方法。由於 MATLAB 對陣列擴充時均以零補足未填入的部份,但有些程式常將零值解讀為終止代碼,如此反而會造成擴充部份之長度未達到全長,因而造成錯誤。

下面的例子是將一個1X5之文字陣列擴充至12個字母,其結果變成一個長字串:


greeting = 'Hello'; greeting(1,8:12) = 'World'
greeting =
Hello World


如果細心審視文字之內碼,變成零值之碼就出現了:


uint8(greeting)
ans =
72 101 108 108 111 0 0 87 111 114 108 100


在字串中間由於零值之出現常會造成一些函數產生不可預測的結果。例如:利用strcmp比較兩字串是否相同時,得到不正確的結果,因為這兩個字串內容實際上是一樣的:

strcmp(greeting, 'Hello World')
ans =
0


上述介紹的方法雖然可以達到擴張矩陣的目的,但若需要重覆進行擴張的動作時,仍然建議不要如此作,因為會浪費電腦計算時間。比較妥當的方式是事先安排足夠的空間,如此可以增加記憶體之運用效率。

10/30/2006

多維陣列範例

多維陣列範例

要產生多維陣列,利用zeros、ones、rand、randn等函數指令亦可完成,例如:


>>W=randn(4,3,5)

W(:,:,1) =

-0.4326 -1.1465 0.3273
-1.6656 1.1909 0.1746
0.1253 1.1892 -0.1867
0.2877 -0.0376 0.7258


W(:,:,2) =

-0.5883 1.0668 0.2944
2.1832 0.0593 -1.3362
-0.1364 -0.0956 0.7143
0.1139 -0.8323 1.6236


W(:,:,3) =

-0.6918 -1.4410 0.8156
0.8580 0.5711 0.7119
1.2540 -0.3999 1.2902
-1.5937 0.6900 0.6686


W(:,:,4) =

1.1908 -1.6041 -0.8051
-1.2025 0.2573 0.5287
-0.0198 -1.0565 0.2193
-0.1567 1.4151 -0.9219


W(:,:,5) =

-2.1707 0.5077 0.3803
-0.0592 1.6924 -1.0091
-1.0106 0.5913 -0.0195
0.6145 -0.6436 -0.0482


其結果等於產生一個4x3x5的陣列,等於60個常態分配之值。這些陣列等於形成五頁。

三維陣列所代表之數值可能也有其他物理意義,例如不同長方形隔間之室溫分佈,或一與時間有關之物理量等等。

設若利用排列組合指令perms(1:4)將1、2、3、4作排列,則應有十六種排法:

>> h=perms(1:4)

h =

4 3 2 1
4 3 1 2
4 2 3 1
4 2 1 3
4 1 2 3
4 1 3 2
3 4 2 1
3 4 1 2
3 2 4 1
3 2 1 4
3 1 2 4
3 1 4 2
2 3 4 1
2 3 1 4
2 4 3 1
2 4 1 3
2 1 4 3
2 1 3 4
1 3 2 4
1 3 4 2
1 2 3 4
1 2 4 3
1 4 2 3
1 4 3 2


其後由魔術方陣產生的矩陣依上述組合依行重排,置於三維陣列M內,則M應可由下指令獲得:


>> for k=1:6, M(:,:,k)=A(:,h(k,:));end
>> M

M(:,:,1) =

13 3 2 16
8 10 11 5
12 6 7 9
1 15 14 4


M(:,:,2) =

13 3 16 2
8 10 5 11
12 6 9 7
1 15 4 14


M(:,:,3) =

13 2 3 16
8 11 10 5
12 7 6 9
1 14 15 4


M(:,:,4) =

13 2 16 3
8 11 5 10
12 7 9 6
1 14 4 15


M(:,:,5) =

13 16 2 3
8 5 11 10
12 9 7 6
1 4 14 15


M(:,:,6) =

13 16 3 2
8 5 10 11
12 9 6 7
1 4 15 14


若利用sum(M,d)這個指令進行加總,則第二參數決定其加總方向,d=1時會以行向進行,但每頁會有一個加總;d=2時則為列向加總,同理,亦應有六頁;d=3為依頁向加總,故其結果應為一4X4之矩陣,其結果如下:

>> sum(M,1) %行向加總

ans(:,:,1) =

34 34 34 34


ans(:,:,2) =

34 34 34 34


ans(:,:,3) =

34 34 34 34


ans(:,:,4) =

34 34 34 34


ans(:,:,5) =

34 34 34 34


ans(:,:,6) =

34 34 34 34

>> sum(M,2) %列向加總

ans(:,:,1) =

34
34
34
34


ans(:,:,2) =

34
34
34
34


ans(:,:,3) =

34
34
34
34


ans(:,:,4) =

34
34
34
34


ans(:,:,5) =

34
34
34
34


ans(:,:,6) =

34
34
34
34

>> sum(M,3) %頁向加總

ans =

78 42 42 42
48 52 52 52
72 44 44 44
6 66 66 66

10/29/2006

3.3輸入之判斷

輸入判斷與隔離

有大部份的輸入必須依靠鍵盤,但常易造成人為疏失,仍然有賴程式加以矯正。下列為一個提示程式,在使用者按enter鍵之後,必須判斷是否與真正的答案有否出入。


%answer.m
%Check the answer
A=input('是否繼續作答 (Y/N)? ','s');
A=upper(A);
if (isempty(A)|A=='Y')
A='Y'
else
A='N'
end 

執行結果:

>> answer
是否繼續作答 (Y/N)? y

A =

Y

3.9由AB二邊求構成之三角形面積

已知AB向量求其構成面積
題意:空間兩向量A與B均通過原點,求其OAB之面積

解析:

通過原點之向量A、B,設

A=a1i+a2j+a3k、B=b1i+b2j+b3k



absA=(a12+a22+a32)(1/2)
absB=(b12+b22+b32)(1/2)

兩向量叉積之向量設為Z,其值應為|AXB|,且等於三角形面積之兩倍。

故截面積=(dot(Z,Z))1/2


%Find the trangular area between vectors A & B
A=[0 0 4],B=[0 4 0]% Vector A & B
AA=cross(A,B)/2 % Cross product of A & B is equivalent to double area
Area=sqrt(dot(AA,AA))



執行結果:


>> triangle

A =

0 0 4


B =

0 4 0


AA =

-8 0 0


Area =

8