Подтвердить что ты не робот

Матрица неизвестной длины в MATLAB?

Я пытаюсь установить нулевую матрицу переменной длины с двумя столбцами, в которые я могу выводить результаты цикла while (с намерением использовать его для хранения данных шага из метода Эйлера с отрегулированными шагами времени). Длина будет определяться количеством итераций цикла.

Мне интересно, есть ли способ, которым я могу это сделать, пока я запускаю цикл, или мне нужно настроить его для начала и как это сделать.

4b9b3361

Ответ 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