Использование векторизации для сокращения для циклов, как использовать условный, если? - PullRequest
0 голосов
/ 26 мая 2019

Я работаю в проекте Matlab, и у меня есть функция, которая работает, но я хочу оптимизировать ее, уменьшив количество циклов for, которые есть в моем коде. Я читал о векторизации , я мог бы использовать его, но как бы я включил условный оператор if, если мне нужно проверять каждое значение за раз?

function [y, zf] = MyFunction(x, b, zi)

y = zeros([length(x) 1]);

for n = 1:length(x)
  for k=1:length(zi)
       if n<k
           y(n) = y(n) + b(k)*zi(length(zi)+(n-k)+1);
       else
           y(n) = y(n) + b(k)*x(n-k+1);
       end
   end
end

zf = x(length(x)-length(zi)+1:length(x));

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

Переменная 'n' может быть установлена ​​нескалярным оператором

function [y, zf] = MyFunction(x, b, zi)

y = zeros([length(x) 1]);

n=1:1:length(x); % use of vectorization
for k=1:length(zi)
   if n<k % problem with if
       y = y + b(k)*zi(length(zi)+(n-k)+1);
   else
       y = y + b(k)*x(n-k+1);
   end
end

zf = x(length(x)-length(zi)+1:length(x));

1 Ответ

3 голосов
/ 27 мая 2019

В настоящее время n является вектором, k является скаляром, а n<k возвращает логический вектор. Если вы непосредственно используете if, это будет то же самое, что и if all(n), который вернет true, только когда все в этом векторе истинно! Это неожиданное поведение.

Я не знаю, есть ли общий способ векторизации кодов с if. Но в вашем случае я могу сделать это следующим образом.

% use indice to deal with if
for k=1:length(zi)
   y(1:k-1)=y(1:k-1)+b(k)*zi(length(zi)+2-k:end);
   y(k:end)=y(k:end)+b(k)*x(1:length(x)-k+1);
end

Я также заметил, что на самом деле, если вы cat zi и x, нет необходимости использовать 2 отдельных утверждения.

% assume both zi & x to be column vector
ziandx=[zi;x];
for k=1:length(zi)
   y=y+b(k)*ziandx(length(zi)+2-k:length(zi)+length(x)-k+1);
end

Наконец, даже этот цикл for не нужен, если вы используете conv. (проверьте документ для более подробной информации)

ziandx=[zi;x];
s=conv(b(1:length(zi)),ziandx);
y=s(length(zi)+1:length(zi)+length(x))

Я рекомендую вам прочитать все три метода и понять идею, поэтому вы можете сделать это самостоятельно в следующий раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...