MATLAB® оптимизирован для операций включающие матрицы и векторы. Процесс пересмотра основанного на цикле, ориентированного на скаляр кода, чтобы использовать матрицу MATLAB и векторные операции называется векторизацией. Векторизация вашего кода стоит по нескольким причинам:
Внешний вид: Векторизованный математический код появляется больше как математические выражения, найденные в учебниках, делая код легче понять.
Менее подверженный ошибкам: Без циклов векторизованный код часто короче. Меньше линий кода означает меньше возможностей ввести программные ошибки.
Производительность: Векторизованный код часто запускается намного быстрее, чем соответствующий код, содержащий циклы.
Этот код вычисляет синус 1 001 значения в пределах от от 0 до 10:
i = 0; for t = 0:.01:10 i = i + 1; y(i) = sin(t); end
Это - векторизованная версия того же кода:
t = 0:.01:10; y = sin(t);
Второй пример кода обычно выполняется быстрее, чем первое и является более эффективным использованием MATLAB. Скорость выполнения теста в вашей системе путем создания скриптов, которые содержат код, показанный, и затем используют tic
и toc
функции, чтобы измерить их время выполнения.
Этот код вычисляет совокупную сумму вектора в каждом пятом элементе:
x = 1:10000; ylength = (length(x) - mod(length(x),5))/5; y(1:ylength) = 0; for n= 5:5:length(x) y(n/5) = sum(x(1:n)); end
Используя векторизацию, можно записать намного более краткий процесс MATLAB. Этот код показывает один способ выполнить задачу:
x = 1:10000; xsums = cumsum(x); y = xsums(5:5:length(x));
Операторы массивов выполняют ту же операцию для всех элементов в наборе данных. Эти типы операций полезны для повторяющихся вычислений. Например, предположите, что вы собираете объем (V
) из различных конусов путем записи их диаметра (D
) и высота (H
). Если вы собираете информацию всего для одного конуса, можно вычислить объем для того одного конуса:
V = 1/12*pi*(D^2)*H;
Теперь соберите информацию относительно 10 000 конусов. Векторы D
и H
каждый содержит 10 000 элементов, и вы хотите вычислить 10 000 объемов. На большинстве языков программирования необходимо настроить цикл, похожий на этот код MATLAB:
for n = 1:10000 V(n) = 1/12*pi*(D(n)^2)*H(n)); end
С MATLAB можно выполнить вычисление для каждого элемента вектора с подобным синтаксисом как скалярный случай:
% Vectorized Calculation
V = 1/12*pi*(D.^2).*H;
Размещение периода (.
) перед операторами *
, /
, и ^
, преобразовывает их в операторы массивов.
Операторы массивов также позволяют вам объединить матрицы различных размерностей. Это автоматическое расширение размера 1 размерность полезно для векторизации создания сетки, матричных и векторных операций и т.д.
Предположим тот матричный A
представляет экзаменационные отметки, строки которых обозначают различные классы. Вы хотите вычислить различие между средней оценкой и отдельной музыкой к каждому классу. Используя цикл, операция похожа:
A = [97 89 84; 95 82 92; 64 80 99;76 77 67;... 88 59 74; 78 66 87; 55 93 85]; mA = mean(A); B = zeros(size(A)); for n = 1:size(A,2) B(:,n) = A(:,n) - mA(n); end
Более прямой способ сделать это с A - mean(A)
, который избегает потребности цикла и значительно быстрее.
devA = A - mean(A)
devA = 18 11 0 16 4 8 -15 2 15 -3 -1 -17 9 -19 -10 -1 -12 3 -24 15 1
Даже при том, что A
7 3 матрица и mean(A)
1 3 вектор, MATLAB неявно расширяет вектор, как будто это имело тот же размер как матрица, и операция выполняется как нормальное поэлементное минус операция.
Требование размера для операндов - то, что для каждой размерности, массивы должны или иметь тот же размер или одного из них, 1. Если это требование удовлетворяется, то размерности, где один из массивов имеет размер 1, расширены, чтобы быть одного размера с соответствующей размерностью в другом массиве. Для получения дополнительной информации см. "Совместимые размеры массивов для основных операций".
Другая область, где неявное расширение полезно для векторизации, - то, если вы работаете с многомерными данными. Предположим, что вы хотите выполнить функцию, F
, из двух переменных, x
и y
.
F(x,y) = x*exp(-x2 - y2)
Выполнять эту функцию в каждой комбинации точек в x
и y
векторы, необходимо задать сетку значений. Для этой задачи необходимо избегать использования циклов, чтобы выполнить итерации через комбинации точки. Вместо этого если один из векторов является столбцом, и другой строка, то MATLAB автоматически создает сетку, когда векторы используются с оператором массивов, таким как x+y
или x-y
. В этом примере, x
21 1 вектор и y
1 16 вектор, таким образом, операция производит 21 16 матрица путем расширения второго измерения x
и первая размерность y
.
x = (-2:0.2:2)'; % 21-by-1 y = -1.5:0.2:1.5; % 1-by-16 F = x.*exp(-x.^2-y.^2); % 21-by-16
В случаях, где вы хотите явным образом создать сетки, можно использовать meshgrid
и ndgrid
функции.
Логическое расширение объемной обработки массивов должно векторизовать сравнения и принятие решения. Операторы сравнения MATLAB принимают векторные входные параметры и возвращают векторные выходные параметры.
Например, предположите при сборе данных от 10 000 конусов, вы записываете несколько отрицательных величин для диаметра. Можно определить, какие значения в векторе допустимы с >=
оператор:
D = [-0.2 1.0 1.5 3.0 -1.0 4.2 3.14]; D >= 0
ans = 0 1 1 1 0 1 1
Vgood
, для которого соответствующие элементы D
являются неотрицательными:Vgood = V(D >= 0);
MATLAB позволяет вам выполнять логический AND или OR на элементах целого вектора с функциями all
и any
, соответственно. Можно выдать предупреждение если все значения D
ниже нуля:
if all(D < 0) warning('All values of diameter are negative.') return end
MATLAB может также сравнить два вектора с совместимыми размерами, позволив вам ввести дальнейшие ограничения. Этот код находит все значения, где V является неотрицательным и D
больше H
:
V((V >= 0) & (D > H))
Чтобы помочь сравнению, MATLAB содержит специальные значения, чтобы обозначить переполнение, потерю значимости и неопределенные операторы, такие как Inf
и NaN
. Логические операторы isinf
и isnan
существуйте, чтобы помочь выполнить логические тесты для этих специальных значений. Например, часто полезно исключить NaN
значения от расчетов:
x = [2 -1 0 3 NaN 2 NaN 11 4 Inf]; xvalid = x(~isnan(x))
xvalid = 2 -1 0 3 2 11 4 Inf
Inf == Inf
возвращает true; однако, NaN == NaN
всегда возвращает false.
При векторизации кода часто необходимо создавать матрицу с конкретным размером или структурой. Методы существуют для создания универсальных матриц. Например, вам может быть нужна матрица 5 на 5 равных элементов:
A = ones(5,5)*10;
v = 1:5; A = repmat(v,3,1)
A = 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
Функциональный repmat
обладает гибкостью в создании матриц из меньших матриц или векторов. repmat
создает матрицы путем повторения входной матрицы:
A = repmat(1:3,5,2) B = repmat([1 2; 3 4],2,2)
A = 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 B = 1 2 1 2 3 4 3 4 1 2 1 2 3 4 3 4
Во многих приложениях вычисления, сделанные на элементе вектора, зависят от других элементов в том же векторе. Например, вектор, x, может представлять набор. Как выполнить итерации через набор без for
или while
цикл не очевиден. Процесс становится намного более ясным и синтаксис, менее громоздкий, когда вы используете векторизованный код.
Много различных путей существуют для нахождения избыточных элементов вектора. Один путь включает функциональный diff
. После сортировки векторных элементов равные смежные элементы производят нулевую запись, когда вы используете diff
функция на том векторе. Поскольку diff(x)
дает вектор, который имеет тот меньше элемента, чем x
, необходимо добавить элемент, который не равен никакому другому элементу в наборе. NaN
всегда удовлетворяет этому условию. Наконец, можно использовать логическую индексацию, чтобы выбрать уникальные элементы в наборе:
x = [2 1 2 2 3 1 3 2 1 3]; x = sort(x); difference = diff([x,NaN]); y = x(difference~=0)
y = 1 2 3
unique
функция:y=unique(x);
unique
функциональная сила обеспечивает больше функциональности, чем необходимо, и замедлите подписание своего кода. Используйте tic
и toc
функции, если вы хотите измерить уровень каждого фрагмента кода.Вместо того, чтобы просто возвращать набор или подмножество, x
, можно считать случаи элемента в векторе. После векторных видов можно использовать find
функция, чтобы определить индексы нулевых значений в diff(x)
и показать, где элементы изменяют значение. Различие между последующими индексами от find
функция указывает на количество случаев для конкретного элемента:
x = [2 1 2 2 3 1 3 2 1 3]; x = sort(x); difference = diff([x,max(x)+1]); count = diff(find([1,difference])) y = x(find(difference))
count = 3 4 3 y = 1 2 3
find
функция не возвращает индексы для NaN
элементы. Можно считать количество NaN
и Inf
значения с помощью isnan
и isinf
функции.count_nans = sum(isnan(x(:))); count_infs = sum(isinf(x(:)));
Функция | Описание |
---|---|
all | Определите, являются ли все элементы массива ненулевыми или верными |
any | Определите, являются ли какие-либо элементы массива ненулевыми |
cumsum | Совокупная сумма |
diff | Разности и аппроксимация производных |
find | Найдите индексы и значения ненулевых элементов |
ind2sub | Индексы от линейного индекса |
ipermute | Инверсия переставляет размерности массива N-D |
logical | Преобразуйте числовые значения в logicals |
meshgrid | Прямоугольная сетка в 2D и трехмерном пространстве |
ndgrid | Прямоугольная сетка на пробеле N-D |
permute | Перестройте размерности массива N-D |
prod | Произведение элементов массива |
repmat | Копирование массива |
reshape | Изменение размерности массива |
shiftdim | Сдвиг размерностей массива |
sort | Сортировка массива |
squeeze | Удалите одноэлементные размерности |
sub2ind | Преобразуйте индексы в линейные индексы |
sum | Сумма элементов массива |