10/31/2006

如何擴張矩陣

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


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

沒有留言: