2009-10-10 157 views
24

我試圖設置一個可變長度的零矩陣,其中有兩列,可以輸出一個while循環的結果(用於使用它來存儲歐拉方法中調整時間步驟的步驟數據) 。長度將由循環的迭代次數決定。MATLAB中未知長度的矩陣?

我想知道是否有一種方法可以在我運行循環時執行此操作,或者我是否需要將其設置爲開始,以及如何執行此操作。

+0

另外,如果這是一個課堂作業,你需要顯示迭代;你可以在你的Euler實現中使用sprintf。 – ccook 2009-10-10 14:55:04

+0

另一個相關的問題:[添加一個向量到一個空的MATLAB矩陣](http://stackoverflow.com/q/781410/97160) – Amro 2012-08-01 17:31:35

回答

14

如果列數是固定的,你可以隨時添加行到您的矩陣(環內)

例如

while (....) 
    ..... 
    new_row =[x y] ; % new row with values x & y 
    mat = [mat ; new_row]; 
當然

,如果你知道迭代次數while循環之前,更高效的預分配矩陣

+0

非常感謝!這對我有意義。 你認爲一個編程單位他們會教我們一些,但他們把我們扔給狼。 Thanks for saving me :) – Flick 2009-10-10 14:50:52

+2

對上面代碼的最後一行使用替代語法使得它更明確地表明您正在擴展矩陣:'mat(end + 1,:) = new_row;' – nhowe 2013-04-18 02:33:02

7

MATLAB使用動態打字和自動內存管理。這意味着,在使用它之前,您不需要聲明一個固定大小的矩陣 - 您可以隨時更改它,MATLAB將爲您動態分配內存。

BUT它是方式更有效地對矩陣進行第一分配內存和然後使用它。但是如果你的程序需要這種靈活性,那就去做吧。

我猜你需要不斷追加行到你的矩陣。下面的代碼應該可以工作。

Matrix = []; 

while size(Matrix,1) <= 10 
    Matrix = [Matrix;rand(1,2)]; 
end 

disp(Matrix); 

這裏,我們動態再分配的Matrix每次添加一個新行時間所需的空間。如果您事先知道,比如您將擁有的行數的上限,則可以聲明Matrix = zeros(20,2),然後逐行將每行插入到矩陣中。

% Allocate space using the upper bound of rows (20) 
Matrix = zeros(20,2); 
k = 1; 
for k = 1:10 
    Matrix(k,:) = rand(1,2); 
end 
% Remove the rest of the dummy rows 
Matrix(k+1:end,:) = []; 
+0

+1我一直都在使用它。請注意,您也可以只使用計數器,而Matlab將增加數組。 – ccook 2009-10-10 14:44:24

+0

我開始看到你在做什麼以及爲什麼它很高效。非常有幫助,謝謝。 – Flick 2009-10-10 15:01:20

47

考慮到這一點具有性能的同時,仍試圖以節省空間的,是預先分配大批量內存的另一種方法,根據需要添加更多的批次。如果您不必事先知道多少項目,就必須添加大量項目,這非常合適。

BLOCK_SIZE = 2000;       % initial capacity (& increment size) 
listSize = BLOCK_SIZE;      % current list capacity 
list = zeros(listSize, 2);     % actual list 
listPtr = 1;        % pointer to last free position 

while rand<1-1e-5       % (around 1e5 iterations on avrg) 
    % push items on list 
    list(listPtr,:) = [rand rand];   % store new item 
    listPtr = listPtr + 1;     % increment position pointer 

    % add new block of memory if needed 
    if(listPtr+(BLOCK_SIZE/10) > listSize) % less than 10%*BLOCK_SIZE free slots 
    listSize = listSize + BLOCK_SIZE;  % add new BLOCK_SIZE slots 
    list(listPtr+1:listSize,:) = 0; 
    end 
end 
list(listPtr:end,:) = [];     % remove unused slots 

EDIT:作爲一個時間比較,考慮以下情況:

  1. 相同的代碼如以上對於50000次迭代完成。
  2. 預分配整個矩陣事先:list = zeros(50000,2); list(k,:) = [x y];
  3. 動態添加向量的矩陣:list = []; list(k,:) = [x y];

在我的機器,結果是:

1)經過時間爲0.080214秒
2)已用時間爲0.065513秒。
3)已用時間爲24.433315秒。


更新:

繼在評論中討論,我已經重新運行使用最新版本R2014b一些測試。結論是,最近的MATLAB版本已經大大提高了自動陣列增長的性能!

但有一個問題;該數組必須在最後一個維度上生長(在2D矩陣的情況下爲列)。這就是爲什麼在不預先分配的情況下追加行像原來預期的那樣仍然太慢。這是上面提出的解決方案真正可以幫助的地方(通過批量擴展數組)。

看到這裏的全套測試:https://gist.github.com/amroamroamro/0f104986796f2e0aa618

+4

哇噢!一個富有洞察力的觀點+測量來證實它。謝謝。 – 2009-10-10 21:44:47

+8

p.s.大多數可變大小的方法(如字符串類)不使用固定的塊大小,而是通過乘法因子K(通常爲K = 2)來增加大小。這將分配步驟數限制爲O(log N),如果您關心內存效率,則始終可以選擇K = 1.2或1.1,並處理數學計算命中以權衡效率/分配步驟數量。 – 2009-10-10 21:48:28

+5

你可能是正確的..你可以很容易地修改代碼來做到這一點。還可以調整一些參數:何時增加尺寸,增加多少,甚至是增長的因素(從K = 1.1開始並增加到2) – Amro 2009-10-10 21:55:56