Матрица неизвестной длины в MATLAB?
Я пытаюсь создать нулевую матрицу переменной длины с двумя столбцами, в которые я могу выводить результаты в цикл while (с намерением использовать его для хранения данных из шага метод Эйлера с уточнением времени действия). Длина будет определяться количеством итераций цикла.
Мне интересно, есть ли способ сделать это, пока я запускаю цикл, или мне нужно настроить его для начала, и как это сделать.
4 ответов
если количество столбцов фиксировано, вы всегда можете добавить строки в свою матрицу (внутри цикла)
например
while (....)
.....
new_row =[x y] ; % new row with values x & y
mat = [mat ; new_row];
конечно, если вы знаете количество итераций до цикла while, более эффективно предварительно выделить матрицу
другой подход, который имеет производительность в виду, все еще пытаясь быть эффективным с пространством, заключается в предварительном распределении памяти большими партиями, добавляя больше партии по мере необходимости. Это хорошо подходит, если вам нужно добавить большое количество товаров, не зная, сколько заранее.
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
редактировать: в качестве сравнения, рассмотрим следующие случаи:
- тот же код, что и выше, для 50000 повторения.
- предварительное распределение всей матрицы заранее:
list = zeros(50000,2); list(k,:) = [x y];
- динамическое добавление векторов в матрицу:
list = []; list(k,:) = [x y];
на моей машине, результаты были:
1) затраченное время 0.080214 секунд.
2) истекшее время 0,065513 секунды.
3) истекшее время 24.433315 секунд.
обновление:
после обсуждения в комментариях, я повторите некоторые тесты, используя последнюю версию r2014b. Вывод состоит в том, что последние версии MATLAB значительно улучшили производительность автоматического роста массива!
однако есть уловка; массив должен расти по последнему измерению (столбцы в случае 2D-матриц). Вот почему добавление строк, как первоначально предполагалось, все еще слишком медленно без предварительного распределения. Именно здесь предлагаемое выше решение может действительно помочь (путем расширения массива в партии.)
см. здесь полный набор тестов:https://gist.github.com/amroamroamro/0f104986796f2e0aa618
MATLAB использует динамическую типизацию с автоматическим управлением памятью. Это означает, что вам не нужно объявлять матрицу фиксированного размера перед ее использованием - вы можете изменить ее по мере продвижения, и MATLAB динамически выделит вам память.
но это путь эффективнее сначала выделить память для матрицы и затем использовать его. Но если ваши программы нуждаются в такой гибкости, идите на это.
Я думаю, что вам нужно продолжайте добавлять строки в матрицу. Следующий код должен работать.
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,:) = [];
еще один аромат того же, что и Джейкоб опубликовал.
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