2009-10-10 17 views
24

Bir while döngüsünün sonuçlarının çıktısını alabildiğim iki sütunu olan sıfır uzunluğundaki bir matris matrisi oluşturmaya çalışıyorum (adım verisini Euler yönteminden ayarlanmış zaman adımlarıyla depolamak için kullanmak amacıyla) . Uzunluk, döngünün yineleme sayısı ile belirlenir.Bilinmeyen uzunluk matrisi?

Döngüyü çalıştırırken ya da başlamak için ayarlamam gerekip gerekmediğini ve bunu yapmaya nasıl devam edeceğimi anlamanın bir yolu olup olmadığını merak ediyorum.

+0

Ayrıca ve yinelemeleri göstermek gerekir;:

testlerin tam set için buraya bakınız Sprintf'i Euler uygulamanızda kullanabilirsiniz. – ccook

+0

Başka bir soru: [Bir boş MATLAB matrisine vektör ekleme] (http://stackoverflow.com/q/781410/97160) – Amro

cevap

14

sütun sayısı (döngü içinde) her zaman matrisin satır ekleyebilirsiniz sabit kalmak şartıyla

örn Tabii

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

bunu daha etkin iken döngü önce yineleme sayısını biliyorsanız matriksi

+0

Çok teşekkür ederim! Bu bana mantıklı geliyor. Bir programlama ünitesi için bize biraz öğrettiklerini düşünürsünüz, ama bizi kurtlara atıyorlar. Beni kurtardığın için teşekkürler :) – Flick

+2

Yukarıdaki kodun son sözdizimini kullanmak, matrisi uzattığınızı daha açık bir hale getiriyor: mat (end + 1, :) = new_row; ' – nhowe

7

MATLAB, otomatik bellek yönetimi ile dinamik yazmayı kullanır. Bu, kullanmadan önce sabit bir boyutta bir matris bildirmeniz gerekmediği anlamına gelir - siz değiştirirken değiştirebilirsiniz ve MATLAB sizin için belleği dinamik olarak ayıracaktır.

ama bu ilk matris için bellek ayırmaya daha verimli bir şekilde ve sonra bunu kullanmak. Ancak, programlarınız bu tür bir esnekliğe ihtiyaç duyuyorsa, bunun için gidin.

Sanırım matrisinize satır eklemeye devam etmeniz gerekiyor. Aşağıdaki kod çalışmalıdır. İşte

Matrix = []; 

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

disp(Matrix); 

, dinamik olarak Matrix için yeni bir satır eklemek her zaman gereken alanı yeniden tahsis ediyoruz. Önceden tanımlayacağınız satırların sayısı üzerinde bir üst sınır olduğunu biliyorsanız, Matrix = zeros(20,2) bildirebilir ve sonra her bir satırı matrisin içine kademeli olarak ekleyebilirsiniz.

% 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 Bunu her zaman kullanıyorum. Sadece bir sayaç kullanabileceğinizi ve Matlab diziyi büyüteceğini unutmayın. – ccook

+0

Ne yaptığınızı ve neden verimli olduğunu görmeye başladım. Çok yardımcı, teşekkürler. – Flick

47

hala alanı daha verimli olmaya çalışarak büyük gruplar halinde hafızayı preallocate için ise akılda performansa sahip başka bir yaklaşım, toplu daha ekledi. Önceden kaç tane olduğunu bilmeden çok sayıda öğe eklemeniz gerekiyorsa, bu çok uygundur.

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 

DÜZENLEME

: Bir zaman Karşılaştırma olarak, aşağıdaki durumlarda göz önünde:

  1. yukarıdaki gibi 50000 tekrarlamalar için yapılan aynı kod.
  2. önce bütün matris preallocating: list = zeros(50000,2); list(k,:) = [x y];
  3. dinamik ilave vektörler, matris: list = []; list(k,:) = [x y];

zaman makine üzerinde sonuçlar şöyle olmuştur:

1) Geçen zaman 0,080214 saniye olup.
2) Geçen süre 0.065513 saniyedir.
3) Geçen süre 24.433315 saniyedir.


Güncelleme: Açıklamalarda

ardından tartışmalar, ben son R2014b bırakılması kullanılarak bazı testler yeniden ettik. Sonuç olarak, MATLAB'ın son versiyonları otomatik dizi büyümesinin performansını büyük ölçüde geliştirdi! Bununla birlikte, bir yakalama vardır; dizi son boyutta büyüyor olmalıdır (2D matrisler durumunda sütunlar). Bu nedenle, orijinal olarak tasarlanan satırların eklenmesi, ön izin olmadan hala çok yavaştır. Yukarıda önerilen çözümün gerçekten işe yaradığı yer burasıdır (dizileri yığın halinde genişleterek). Bu bir sınıf atama için ise, https://gist.github.com/amroamroamro/0f104986796f2e0aa618

+4

woohoo! Doğrulamak için anlayışlı bir nokta + ölçümler. Teşekkürler. –

+8

p.s. en değişken boyuttaki yöntemler (dizgi sınıfları gibi) sabit bir blok boyutu kullanmaz, daha ziyade bir çarpım katsayısı K (genellikle K = 2) ile boyutu artırır. Bu, atama adımlarının O (log N) 'ye sınırlanmasını sağlar ve eğer bellek verimliliğini önemsiyorsanız, K = 1.2 veya 1.1'i seçebilir ve verim/adım tahsisi adımlarını aşmak için matematik hesaplama isabeti ile uğraşabilirsiniz. –

+5

muhtemelen haklısınız. Bunu yapmak için kodu kolayca değiştirebilirsiniz. Bir dizi parametre de ayarlanabilir: ne kadar büyüyecek, ne kadar büyüyecek, belki de artan bir faktör (K = 1.1'den başlayıp 2'ye kadar artış) – Amro