2009-10-10 21 views
24

私はwhileループの結果を出力できる2つの列を持つ可変長のゼロ行列を設定しようとしています(調整された時間ステップを持つオイラーの方法からのステップデータを格納するために使用する予定です) 。長さは、ループの反復回数によって決まります。MATLABで長さが不明な行列はありますか?

ループを実行している間にこれを行う方法があるかどうか、またはそれを設定する必要があるかどうか、それをどうやって行うかについては疑問に思っています。

+0

、これはクラスの割り当てのためであり、あなたが反復を示す必要がある場合。オイラーの実装でsprintfを使用することができます。 – ccook

+0

もう一つの関連する質問:[空のMATLAB行列にベクトルを追加する](0120-18753) – Amro

答えて

14

列の数は、(ループ内で)あなたは常にあなたの行列に行を追加することができます固定されている場合

例えば当然の

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

あなたはそれを事前に割り当てるマトリックス

+0

ありがとうございました!これは私には意味がある。 プログラミング単位のために、いくつかのことを教えてくれると思うのですが、代わりに私たちをオオカミに投げ捨てます。私を保存していただきありがとうございます:) – Flick

+2

上記のコードの最後の行に代替構文を使用すると、行列を拡張していることがより明確になります: – nhowe

7

MATLABは、自動メモリ管理による動的な型指定を使用します。つまり、使用する前に固定サイズの行列を宣言する必要はありません。移動するにつれて変更することができ、MATLABは動的にメモリを割り当てます。

BUTそれを使用し、次いで第1の行列のためのメモリーを割り当てることがは、より効率的な方法とあります。しかし、あなたのプログラムがこの種の柔軟性を必要とするなら、それに行きましょう。

あなたの行列に行を追加し続ける必要があると思います。次のコードは動作するはずです。ここで

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

+0

私はあなたが何をしているのか、それがなぜ効率的であるのかを見始めています。とても助かりました、ありがとう。 – Flick

4

にヤコブが掲載同じものの別の味がより効率的ですwhileループの前に反復回数を知っていれば。

for counter = 1:10 
    Matrix(counter,:) = rand(1,2); 
end 
disp(Matrix); 

これについて「良い」ことは、パフォーマンスに役立つ最小のサイズを推測できることです。

これは、同様に参考になります。まだスペース効率になろうとしながら、心の中で性能を有するhttp://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-88760

+0

+1 - クリーナー – Jacob

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

woohoo!洞察力のある点+それを裏付ける測定値。ありがとう。 –

+8

p.s.ほとんどの可変サイズメソッド(文字列クラスなど)は固定ブロックサイズを使用せず、倍率K(通常はK = 2)だけサイズを増やします。これはO(log N)に割り当てステップ数を制限し、メモリ効率を気にするならば、常にK = 1.2または1.1を選択し、効率/割り当てステップ数をトレードオフするために計算のヒット数を扱うことができます。 –

+5

あなたはおそらく正しいでしょう。あなたはそのようなコードを簡単に変更することができます。いくつかのパラメータを調整することもできます:サイズを増やすタイミング、増強するタイミング(K = 1.1から2まで増やす) – Amro

関連する問題