2009-10-10 29 views
24

Tôi đang cố gắng thiết lập ma trận có độ dài biến đổi bằng hai cột mà tôi có thể xuất kết quả của một vòng lặp while (với ý định sử dụng nó để lưu trữ dữ liệu bước từ phương pháp Euler với các bước thời gian đã điều chỉnh) . Độ dài sẽ được xác định bởi số lần lặp của vòng lặp.Ma trận có độ dài không xác định trong MATLAB?

Tôi tự hỏi nếu có cách nào tôi có thể làm điều này trong khi tôi đang chạy vòng lặp hoặc liệu tôi có cần thiết lập để bắt đầu và cách thực hiện điều đó hay không.

+0

Ngoài ra, nếu đây là nhiệm vụ của lớp và bạn cần hiển thị các lần lặp; bạn có thể sử dụng sprintf trong việc thực hiện Euler của bạn. – ccook

+0

Một câu hỏi liên quan khác: [Gắn thêm vectơ vào ma trận MATLAB trống] (http://stackoverflow.com/q/781410/97160) – Amro

Trả lời

14

nếu số cột là cố định bạn luôn có thể thêm hàng để ma trận của bạn (bên trong vòng lặp)

ví dụ

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

tất nhiên nếu bạn biết số lần lặp lại trước khi vòng lặp while nó hiệu quả hơn tiền phân bổ các ma trận

+0

Cảm ơn bạn rất nhiều! Điều này có ý nghĩa với tôi. Bạn nghĩ rằng đối với một đơn vị lập trình, họ sẽ dạy cho chúng tôi một số điều, nhưng thay vào đó họ ném chúng tôi đến những con sói. Cảm ơn bạn đã cứu tôi :) – Flick

+2

Sử dụng cú pháp thay thế cho dòng cuối cùng của mã ở trên làm cho nó rõ ràng hơn rằng bạn đang mở rộng ma trận: 'mat (kết thúc + 1, :) = new_row;' – nhowe

7

MATLAB sử dụng tính năng nhập động với quản lý bộ nhớ tự động. Điều này có nghĩa, bạn không cần phải khai báo một ma trận có kích thước cố định trước khi sử dụng nó - bạn có thể thay đổi nó khi bạn đi và MATLAB sẽ tự động cấp phát bộ nhớ cho bạn.

NHƯNG nó là cách hiệu quả hơn để cấp phát bộ nhớ cho ma trận đầu tiên và sau đó sử dụng nó. Nhưng nếu các chương trình của bạn cần loại tính linh hoạt này, hãy thực hiện nó.

Tôi đoán bạn cần phải tiếp tục thêm hàng vào ma trận của mình. Mã sau đây sẽ hoạt động.

Matrix = []; 

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

disp(Matrix); 

Ở đây, chúng tôi đang phân bổ lại không gian cần thiết cho Matrix mỗi lần bạn thêm hàng mới. Nếu bạn biết trước, nói, một giới hạn trên về số lượng hàng bạn sẽ có, bạn có thể khai báo Matrix = zeros(20,2) và sau đó chèn mỗi hàng vào ma trận gia tăng.

% 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 Tôi sử dụng tất cả thời gian này. Lưu ý rằng bạn cũng có thể sử dụng bộ đếm và Matlab sẽ phát triển mảng. – ccook

+0

Tôi bắt đầu thấy những gì bạn đang làm và tại sao nó hiệu quả. Rất hữu ích, cảm ơn bạn. – Flick

47

Một cách tiếp cận có hiệu quả trong tâm trí trong khi vẫn cố gắng trở thành không gian hiệu quả, là để preallocate bộ nhớ theo lô lớn, thêm khi cần thiết. Điều này rất phù hợp nếu bạn phải thêm một số lượng lớn các mục mà không biết trước bao nhiêu.

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: Như một sự so sánh thời gian, hãy xem xét các trường hợp sau:

  1. Mã tương tự như thực hiện trên cho 50000 lần lặp lại.
  2. Preallocating toàn bộ ma trận trước: list = zeros(50000,2); list(k,:) = [x y];
  3. vectơ động thêm vào ma trận: list = []; list(k,:) = [x y];

Trên máy tính của tôi, kết quả là:

1) đã trôi qua là thời gian là 0,080214 giây.
2) Thời gian trôi qua là 0,065513 giây.
3) Thời gian trôi qua là 24.433315 giây.


Cập nhật:

Sau các cuộc thảo luận trong các ý kiến, tôi đã chạy lại một số xét nghiệm bằng cách sử dụng phiên bản mới nhất R2014b. Kết luận là các phiên bản gần đây của MATLAB đã cải thiện đáng kể hiệu suất tăng trưởng mảng tự động!

Tuy nhiên, có sự bắt giữ; mảng phải được phát triển trên kích thước cuối cùng (cột trong trường hợp ma trận 2D). Đó là lý do tại sao việc thêm các hàng như dự định ban đầu vẫn còn quá chậm mà không cần preallocation. Đây là nơi giải pháp được đề xuất ở trên thực sự có thể giúp (bằng cách mở rộng mảng theo lô).

Xem tại đây để có tập hợp đầy đủ các bài kiểm tra: https://gist.github.com/amroamroamro/0f104986796f2e0aa618

+4

woohoo! một điểm sâu sắc + các phép đo để chứng thực nó. cảm ơn. –

+8

p.s. hầu hết các phương thức có kích thước biến (như các lớp chuỗi) không sử dụng kích thước khối cố định, nhưng thay vì tăng kích thước bằng một nhân tố K (thường là K = 2). Điều này giới hạn số bước phân bổ cho O (log N), và nếu bạn quan tâm về hiệu quả bộ nhớ, bạn luôn có thể chọn K = 1.2 hoặc 1.1 và đối phó với phép tính toán để đánh đổi hiệu quả/# của các bước phân bổ. –

+5

bạn có thể đúng .. bạn có thể dễ dàng sửa đổi mã để làm như vậy. Một số thông số cũng có thể được điều chỉnh: khi tăng kích thước, bao nhiêu, thậm chí có thể là một yếu tố đang tăng (bắt đầu từ K = 1.1 và tăng lên đến 2) – Amro