Saturday 4 February 2017

Moyenne Mobile Pondérée C Code

Est-il possible de mettre en œuvre une moyenne mobile en C sans la nécessité d'une fenêtre d'échantillons Ive trouvé que je peux optimiser un peu, en choisissant une taille de fenêtre thats une puissance de deux pour permettre le décalage de bits au lieu de diviser, mais pas besoin Un tampon serait bien. Existe-t-il un moyen d'exprimer un nouveau résultat de la moyenne mobile uniquement en fonction de l'ancien résultat et du nouvel échantillon Définir un exemple de moyenne mobile, à travers une fenêtre de 4 échantillons pour être: Ajouter un nouvel échantillon e: Une moyenne mobile peut être implémentée récursivement , Mais pour un calcul exact de la moyenne mobile, vous devez vous souvenir de l'échantillon d'entrée le plus ancien dans la somme (c'est-à-dire l'a dans votre exemple). Pour une longueur N moyenne mobile que vous calculez: où yn est le signal de sortie et xn est le signal d'entrée. Eq. (1) peut être écrit récursivement comme So Il faut toujours se souvenir de l'échantillon xn-N pour calculer (2). Comme l'a souligné Conrad Turner, vous pouvez utiliser une fenêtre exponentielle (infiniment longue) qui vous permet de calculer la sortie uniquement à partir de la sortie passée et de l'entrée courante: mais ce n'est pas une moyenne mobile standard (non pondérée) mais une valeur exponentielle (Au moins en théorie) vous n'oubliez jamais rien (les poids sont de plus en plus petits pour les échantillons loin dans le passé). J'ai mis en œuvre une moyenne mobile sans mémoire élément individuel pour un programme de suivi GPS que j'ai écrit. Je commence par 1 échantillon et diviser par 1 pour obtenir le courant avg. J'ajoute ensuite un autre échantillon et divise par 2 la valeur actuelle. Cela continue jusqu'à ce que j'arrive à la longueur de la moyenne. Chaque fois par la suite, j'ajoute dans le nouvel échantillon, obtenez la moyenne et retirez cette moyenne du total. Je ne suis pas un mathématicien, mais cela semblait être une bonne façon de le faire. J'ai pensé que cela transformerait l'estomac d'un vrai mec de maths, mais il s'avère que c'est l'un des moyens acceptés de le faire. Et ça marche bien. Rappelez-vous juste que plus votre longueur est plus lente, il suit ce que vous voulez suivre. Cela peut ne pas importe la plupart du temps, mais en suivant les satellites, si vous êtes lent, le sentier pourrait être loin de la position réelle et il sera mauvais. Vous pourriez avoir un écart entre le sat et les points de fuite. J'ai choisi une longueur de 15 mise à jour 6 fois par minute pour obtenir un lissage adéquat et ne pas trop loin de la position réelle sat avec les points de sentier lissée. Répondu 16 nov 16 à 23:03 initialiser total 0, count0 (chaque fois que vous voyez une nouvelle valeur Puis une entrée (scanf), un add totalValeur, un incrément (comptage), une moyenne de division (totalcount) Ce serait une moyenne mobile Toutes les entrées Pour calculer la moyenne sur les seules 4 dernières entrées, il faudrait 4 variables d'entrée, peut-être copier chaque entrée à une variable d'entrée plus ancienne, puis calculer la nouvelle moyenne mobile comme somme des 4 variables d'entrée, divisée par 4 Bon si toutes les entrées étaient positives pour rendre le calcul moyen répondu Feb 3 15 à 4:06 Cela va effectivement calculer la moyenne totale et PAS la moyenne mobile. 3 15 à 13:53 Votre réponse 2017 Stack Exchange, Inc Je suis en train de calculer la moyenne mobile d'un signal. La valeur du signal (un double) est mis à jour au hasard fois. Je cherche un moyen efficace de calculer sa moyenne pondérée dans le temps Sur une fenêtre temporelle, en temps réel. Je pouvais le faire moi-même, mais c'est plus difficile que je pensais. La plupart des ressources que j'ai trouvées sur Internet sont le calcul de la moyenne mobile du signal périodique, mais les mises à jour de la mine au hasard. Est-ce que quelqu'un sait de bonnes ressources pour cela L'astuce est la suivante: Vous obtenez des mises à jour au hasard fois via la mise à jour vide (temps int, valeur flottante). Cependant, vous devez aussi suivre quand une mise à jour tombe de la fenêtre de temps, de sorte que vous définissez une alarme qui a appelé à l'heure N qui supprime la mise à jour précédente d'être jamais considéré à nouveau dans le calcul. Si cela se produit en temps réel, vous pouvez demander au système d'exploitation de faire un appel à une méthode void dropoffoldestupdate (int time) à appeler au moment N Si c'est une simulation, vous ne pouvez pas obtenir d'aide du système d'exploitation et vous devez Le faire manuellement. Dans une simulation, on appellerait des méthodes avec le temps fourni comme argument (qui ne correspond pas au temps réel). Cependant, une hypothèse raisonnable est que les appels sont garantis pour être tels que les arguments de temps sont en augmentation. Dans ce cas, vous devez conserver une liste triée des valeurs d'heure d'alarme et pour chaque mise à jour et appel de lecture vous vérifiez si l'argument de temps est supérieur à la tête de la liste d'alarmes. Bien qu'il soit plus important, vous effectuez le traitement d'alarme (déposez la mise à jour la plus ancienne), retirez la tête et vérifiez à nouveau jusqu'à ce que toutes les alarmes avant le moment donné soient traitées. Ensuite, effectuez l'appel de mise à jour. J'ai jusqu'à présent supposé qu'il est évident ce que vous feriez pour le calcul réel, mais je vais élaborer juste au cas où. Je suppose que vous avez une méthode float read (int time) que vous utilisez pour lire les valeurs. L'objectif est de rendre cet appel aussi efficace que possible. Donc, vous ne calculez pas la moyenne mobile chaque fois que la méthode de lecture est appelée. Au lieu de cela vous précomputer la valeur à partir de la dernière mise à jour ou la dernière alarme et ajuster cette valeur par un couple d'opérations en virgule flottante pour tenir compte du passage du temps depuis la dernière mise à jour. (C'est-à-dire un nombre constant d'opérations sauf pour le traitement peut-être d'une liste d'alarmes). Espérons que cela est clair - ce devrait être un algorithme assez simple et très efficace. Optimisation ultérieure. L'un des problèmes restants est si un grand nombre de mises à jour se produisent dans la fenêtre de temps, puis il ya une longue période pour laquelle il n'y a ni lectures ni mises à jour, puis une lecture ou une mise à jour arrive. Dans ce cas, l'algorithme ci-dessus sera inefficace dans la mise à jour incrémentielle de la valeur de chacune des mises à jour qui est en baisse. Cela n'est pas nécessaire car nous ne nous soucions de la dernière mise à jour au-delà de la fenêtre de temps si il ya un moyen de déposer efficacement toutes les mises à jour plus anciennes, il serait utile. Pour ce faire, nous pouvons modifier l'algorithme pour faire une recherche binaire de mises à jour pour trouver la mise à jour la plus récente avant la fenêtre de temps. S'il ya relativement peu de mises à jour qui doivent être supprimées, il est possible de mettre à jour progressivement la valeur de chaque mise à jour abandonnée. Mais s'il ya beaucoup de mises à jour qui doivent être supprimées, alors on peut recalculer la valeur à partir de zéro après avoir abandonné les anciennes mises à jour. Annexe sur le calcul incrémental: Je devrais préciser ce que je veux dire par le calcul incrémental ci-dessus dans la phrase de tordre cette valeur par un couple d'opérations en virgule flottante pour tenir compte du passage du temps depuis la dernière mise à jour. Calcul initial non incrémentiel: itérer ensuite sur les dates d'actualisation en fonction de l'augmentation du temps: movingaverage (sum lastupdate timesincelastupdate) windowlength. Maintenant, si exactement une mise à jour tombe de la fenêtre mais pas de nouvelles mises à jour arriver, ajuster la somme comme: (note c'est priorupdate qui a son horodatage modifié au début de la dernière fenêtre début). Et si exactement une mise à jour entre dans la fenêtre, mais qu'aucune nouvelle mise à jour ne s'arrête, ajustez la somme comme: Comme cela devrait être évident, il s'agit d'un schéma approximatif mais nous espérons qu'il vous montrera comment vous pouvez maintenir la moyenne telle que c'est O (1) Sur une base amortie. Mais remarquez une optimisation supplémentaire dans le paragraphe précédent. Notez également les problèmes de stabilité mentionnés dans une réponse plus ancienne, ce qui signifie que des erreurs de virgule flottante peuvent s'accumuler sur un grand nombre d'opérations incrémentielles telles qu'il ya une divergence par rapport au résultat du calcul complet qui est significatif pour l'application. Si une approximation est OK et theres un temps minimum entre les échantillons, vous pouvez essayer de super-échantillonnage. Avoir un tableau qui représente des intervalles de temps régulièrement espacés qui sont plus courts que le minimum, et à chaque période de temps stocker le dernier échantillon qui a été reçu. Plus l'intervalle est court, plus la moyenne sera proche de la valeur réelle. La période ne doit pas être supérieure à la moitié du minimum ou il est possible de manquer un échantillon. Répondre Dec 15 11 at 18:12 réponse Dec 15 11 at 22:38 Merci pour la réponse. Une amélioration qui serait nécessaire pour quotcachequot la valeur de la moyenne totale donc nous don39t boucle tout le temps. En outre, il peut être un point mineur, mais ne serait-il pas plus efficace d'utiliser un deque ou une liste pour stocker la valeur, puisque nous supposons que la mise à jour viendra dans le bon ordre. L'insertion serait plus rapide que dans la carte. Ndash Arthur Dec 16 11 at 8:55 Oui, vous pouvez mettre en cache la valeur de somme. Soustrayez les valeurs des échantillons que vous effacez, ajoutez les valeurs des échantillons que vous insérez. Aussi, oui, un dequeltpairltSample, Dategtgt pourrait être plus efficace. J'ai choisi la carte pour la lisibilité, et la facilité d'invoquer map :: upperbound. Comme toujours, écrire le code correct en premier, puis profil et mesurer les changements incrémentiels. Ndash Rob Dec 16 11 at 15:00 Note: Apparemment, ce n'est pas la façon d'aborder cela. Laissant ici pour référence sur ce qui ne va pas avec cette approche. Vérifiez les commentaires. MISE À JOUR - basé sur Olis commentaire. Pas sûr de l'instabilité dont il parle cependant. Utilisez une carte triée des heures d'arrivée en fonction des valeurs. À l'arrivée d'une valeur ajouter l'heure d'arrivée à la carte triée avec sa valeur et mettre à jour la moyenne mobile. Avertissement c'est pseudo-code: Là. Pas complètement étoffé mais vous obtenez l'idée. Choses à noter. Comme je l'ai dit le code ci-dessus est pseudo. Vous aurez besoin de choisir une carte appropriée. Ne supprimez pas les paires pendant l'itération car vous invalidez l'itérateur et vous devrez recommencer. Voir Olis commentaire ci-dessous aussi. Répondre Dec 15 11 at 12:22 Ce doesn39t travail: il doesn39t prendre en compte quelle proportion de la fenêtre de longueur chaque valeur existe pour. En outre, cette approche d'addition et de soustraction est seulement stable pour les types d'entiers, pas les flotteurs. Ndash Oliver Charlesworth Dec 15 11 at 12:29 OliCharlesworth - désolé j'ai manqué quelques points clés dans la description (double et pondéré en temps). Je vais mettre à jour. Merci. Ndash Dennis Dec 15 11 at 12:33 La pondération de temps est encore un autre problème. Mais ce n'est pas ce dont je parle. Je faisais allusion au fait que quand une nouvelle valeur entre d'abord dans la fenêtre de temps, sa contribution à la moyenne est minime. Sa contribution continue d'augmenter jusqu'à l'entrée d'une nouvelle valeur. Ndash Oliver Charlesworth Dec 15 11 à 12: 35C algorithme de la latence exponentielle exponentielle de la moyenne mobile Dernière mise à jour: 2012-08-13 Ive essayé de mettre en œuvre une coupure basse fréquence dans c qui prend essentiellement un flux de nombres et lisse la sortie ( Filtrage de mouvement de haute fréquence), mais il est important que les nombres pondérés avant sont considérés immédiatement comme les données est temps critique (il est de contrôler une base de simulation de mouvement en utilisant la sortie d'un peu de logiciel de jeu). Ive a obtenu un algorithme de moyenne mobile pondérée de travail mais pourrait faire avec quelque chose un peu plus sensible à l'extrémité avant, et j'ai trouvé ceci: - Le pseudo-code y est comme suit: Entrées: Prix (NumericSeries), Période (NumericSimple) Variables: (0), retard (0) si CurrentBar lt 1 commence alors ZLEMA Facteur de prix 2 (Period1) lag (Période-1) 2 fin else begin Facteur ZLEMA (2Price-Pricelag) (1-facteur) ZLEMA1 end Ive translated it in À C et mon code est comme suit: Cependant, il ne semble pas se comporter tout à fait comme l'espère. Il semble être presque là, mais parfois, je obtenir une valeur légèrement inférieure à tous les éléments de la file d'attente (quand ils sont tous plus élevés). Ma file d'attente et le nombre d'éléments sont passés comme paramètres, le plus récent étant à l'avant en tout temps, aussi je passe un compteur d'incrémentation commençant à 0 comme requis par la fonction. Im pas sûr Ive interprété la signification de ZLEMA1 correctement comme il n'est pas clair dans son pseudocode, donc j'ai supposé que ce soit les derniers appels zlema et aussi Im en supposant que le prix signifie réellement Price0. Peut-être que j'ai eu ce tort Est-ce que je suis censé être la copie des valeurs réelles zlema calculé retour à ma file d'attente d'origine avant le prochain appel Je ne changez pas la file d'attente d'origine à tous les autres que simplement déplacer toutes les valeurs un à la fin et insérer le dernier au début . Le code que j'utilise pour faire ceci est: Serait extrêmement reconnaissant si quelqu'un avec une meilleure compréhension des mathématiques pourrait s'il vous plaît santé vérifier cela pour moi de voir si j'ai eu quelque chose légèrement mal Merci si longtemps à l'avance si vous pouvez aider Tout d'abord grâce à tous pour Votre entrée, très appréciée Cela fait sens je devine, donc je suppose que le meilleur que je peux espérer est simplement une moyenne mobile exponentielle, en acceptant il y aura un peu de retard, mais ce sera minimisé par la pondération plus lourde avant que donné en typés pondérés Moyenne mobile J'ai cet algorithme aussi, mais un problème similaire en ce que les valeurs ne semblent pas tout à fait correct (sauf si c'est la nature de la formule). Par exemple, disons que mon tableau contient 16 valeurs, toutes les 0.4775 - la sortie est 0.4983, mais je m'attends à ce qu'elle soit 0.4775 Est-ce que ça vous regarde bien. Moyenne mobile exponentielle. Float ema (float vals, int numVals, int currentSample) facteur de flottement statique 0 static float lastema 0 float ema si (currentSample lt 1) ema vals0 facteur 2.0 ((float) numVals) 1.0) else ema (factor vals0) - facteur) lastema) lastema ema return ema Inversement, parfois la sortie est inférieure à chacune des entrées, même si tous sont plus élevés. Il est appelé de la même manière que zlema (.) Ci-dessus, avec un compteur d'incrémentation. La formule et le pseudocode pour celui-ci sont ici: - autotradingstrategy. wordpress20091130exponential-moving-average Merci encore, excuses pour mon malentendu de certaines des bases :( Cordialement, Chris J En ce qui concerne le code que j'ai posté, vous avez raison sur la taille du tableau En ce qui concerne vos questions: 1) La constante de filtre représente une coupure de fréquence. J'ai utilisé un Digital Signal Processing (DSP) pour cette technique. Fr. wikipedia. orgwi kiLow-pas sfilter est une explication simple. Vous voulez la section Réalisation de temps discret. Dans mon cas, le A est le RC-Constant dont ils parlent. Ainsi, la fréquence de coupure est supérieure à 1 (2piA). Si vous n'avez pas une compréhension de la théorie du domaine fréquentiel, cela peut devenir compliqué. Dans votre cas, plus vous faites de A, plus la fréquence que ce filtre va permettre, c'est-à-dire qu'elle lisse la courbe de plus en plus. Plus vous le faites, plus le bruit est permis dans le système. Rappelez-vous que A doit être supérieur ou égal à 1 pour être efficace. J'ai rattaché le XLS à nouveau, cette fois sans les numéros chang rand (). Réglez la constante A et regardez comment il quotsmoothsquot (ou des filtres) sur les variations de haute fréquence. 2) Le dernier point du tableau d'entrée a la valeur la plus récente. 3) Il en va de même pour le tableau de sortie. La dernière est la valeur la plus récente. 5) Le NUMVALS est arbitraire. Vous pouvez continuellement ajouter sur le tableau d'entrée et de sortie autant de fois que youd comme et il wouldnt effet le filtre. En particulier, j'ai utilisé 49 points. Mais je peux facilement supprimer les 20 dernières et les 29 premières sorties restent les mêmes. La fonction n'est pas basée sur le nombre de points utilisés. Je voudrais mentionner que j'ai développé cette fonction pour une conversion ponctuelle. Si vous voulez faire une conversion pour la prochaine valeur à la volée, vous pouvez essayer quelque chose de plus simple (comme ci-joint). Encore une fois rouillée sur c. J'espère que c'est juste. La seule chose que vous devez fournir est la constante d'entrée et de filtre. Faites-moi savoir si cela vous aide.


No comments:

Post a Comment