Встроенный Matlab: проблема с постоянными переменными - PullRequest
2 голосов
/ 14 февраля 2010

Я написал некоторую функцию, которая использует постоянные переменные, например:

function y = integrator(x, t)
persistent yr; %result
...

и затем, если я вызову его только один раз в цикле, все работает нормально:

x = integrator(x_dot, t);

но если я хочу вызвать его дважды с разными аргументами, это даст неверные результаты:

x = integrator(x_dot, t);
y = integrator(y_dot, t);

Это не неожиданно, но как я могу с этим справиться? Использовать что-то другое (непостоянные) переменные или что?

Я привык иметь дело главным образом с Simulink, и решение для меня не очевидно.

Ответы [ 3 ]

2 голосов
/ 14 февраля 2010

Вы можете использовать замыкание для этого:

function integrator_handle = make_integrator(yr)

  function y = integrator(x, t)
    y = x + yr;
    yr = yr + 1;
  end

integrator_handle = @integrator; % (1)
end

Для использования:

>> integrator1 = make_integrator(0); % 0 is the initial value for yr
>> integrator2 = make_integrator(1);

integrator1 и integrator2 теперь являются дескрипторами функций с состоянием, по сути, замыканиями, которые зафиксировали состояние yr, как это было в момент создания дескриптора функции (строка, помеченная комментарием «% (1)»). Их можно вызвать с помощью индексации в скобках, который выглядит так же, как и вызов функции:

у = интегратор 1 (х, т);

Любые изменения yr во время выполнения дескриптора функции будут сохраняться с помощью дескриптора функции, поэтому в моем примере выше yr будет увеличиваться на единицу при каждом вызове интегратора, но только для этого конкретного экземпляра. интегратора.

1 голос
/ 14 февраля 2010

Лучшее решение изменит то, что у вас есть, на что-то вроде:

function [y, yr] = integrator(x, t, yr)
if nargin < 3
    yr = []; % will behave identically to persistent when yr is not given
end

Теперь вы можете совершать повторные звонки как:

[x,xr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);

[y,yr] = integrator(x, t);
[y,yr] = integrator(x, t, yr);

Хотя я бы не рекомендовал этого, есть способ сохранить текущую реализацию, и почти достигнет желаемого результата. Можно очистить постоянные переменные, очистив функцию. Это позволит вам «сбросить» постоянную переменную, что означает, что эта последовательность вызовов должна работать:

x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);

Но учтите, что это, скорее всего, не даст ожидаемого результата при вызове

x = integrator(x_dot, t);
clear integrator;
y = integrator(y_dot, t);
clear integrator;
x = integrator(x_dot, t);

В то время как в решении, которое я предлагаю сначала, вы можете позвонить

[x,xr] = integrator(x, t);
[y,yr] = integrator(x, t);
[x,xr] = integrator(x, t, xr);
[y,yr] = integrator(x, t, yr);

и результаты будут поддерживать состояние, как и ожидалось.

0 голосов
/ 14 февраля 2010

Вы можете просто отправлять и возвращать переменную yr в функцию каждый раз. Для приведенного выше кода вам понадобится переменная x_yr и y_yr. Это может быть не очень элегантно, но это сработает.

Если вам нужны только два экземпляра этой функции (как указано выше для x и y), вы можете создать две идентичные функции, кроме имени, например xintegrator и yintegrator. Или, вы можете указать yr как массив и иметь параметр, отправляемый при вызове интегратора, указывающий, какое значение в массиве использовать.

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