2010-02-14 3 views
2

j'ai écrit une fonction, qui utilise des variables persistantes, par exemple:intégré Matlab: Problème avec les variables persistantes

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

puis, si je l'appelle une seule fois dans un cycle, tout fonctionne bien:

x = integrator(x_dot, t); 

mais si je veux l'appeler deux fois avec des arguments différents, il donnera des résultats erronés:

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

T son n'est pas inattendu, mais comment puis-je faire face à cela? Utiliser des variables différentes (non persistantes) ou quoi?

Je suis habitué à traiter principalement avec Simulink et la solution n'est pas évidente pour moi.

Répondre

0

Vous pouvez simplement envoyer et renvoyer la variable yr à la fonction à chaque fois. Pour votre code ci-dessus, vous devez avoir une variable x_yr et une variable y_yr. Ce n'est peut-être pas très élégant, mais ça marcherait.

Si vous ne voulez que deux instances de cette fonction (comme ci-dessus avec x et y) alors vous pouvez faire deux fonctions qui sont identiques sauf dans un nom comme xintegrator et yintegrator. Ou, vous pourriez avoir un tableau et avoir un paramètre envoyé lors de l'appel de l'intégrateur en spécifiant quelle valeur dans le tableau à utiliser.

1

La meilleure solution changerait ce que vous avez à quelque chose comme:

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

Maintenant, vous pouvez faire des appels répétés comme:

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

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

Bien que je ne le recommanderais pas, il y a un moyen pour garder votre implémentation actuelle et presque atteindre le résultat souhaité. Il est possible d'effacer les variables persistantes en effaçant la fonction. Cela vous permettra à la variable persistante « reset », ce qui signifie que cette séquence d'appels devrait fonctionner:

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

Mais notez que cela produira probablement pas le résultat escompté lors de l'appel

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

Alors que dans la solution que je suggère d'abord vous pouvez appeler

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

et les résultats vont maintenir l'état comme prévu.

2

Vous pouvez utiliser une fermeture pour cela:

function integrator_handle = make_integrator(yr) 

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

integrator_handle = @integrator; % (1) 
end 

Pour utiliser:

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

intégrateur 1 et integrator2 sont maintenant gère la fonction stateful, essentiellement des fermetures qui ont capturé l'état d'année comme il était au point où le handle de fonction a été créé (la ligne marquée du commentaire "% (1)").Ils peuvent être appelés à l'aide entre parenthèses-indexation, qui ressemble à l'invocation de la fonction:

y = intégrateur 1 (x, t);

Toute modification par an au cours de l'exécution de la poignée de fonction seront conservés avec la poignée de fonction, donc dans mon exemple ci-dessus, an gardera incrémenter par un à chaque fois un intégrateur est appelé, mais seulement pour cette instance particulière de l'intégrateur.

Questions connexes