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