Weighted moving average filter c ++


É possível implementar uma média móvel em C sem a necessidade de uma janela de amostras Ive descobri que eu posso otimizar um pouco, escolhendo um tamanho de janela thats um poder de dois para permitir bit-shifting em vez de dividir, mas não necessitando Um buffer seria bom. Existe uma maneira de expressar um novo resultado da média móvel apenas como uma função do antigo resultado e da nova amostra Definir um exemplo de média móvel, através de uma janela de 4 amostras para ser: Adicionar nova amostra e: Uma média móvel pode ser implementada recursivamente , Mas para um cálculo exato da média móvel você deve se lembrar da amostra de entrada mais antiga na soma (ou seja, o a no seu exemplo). Para um comprimento N média móvel você calcula: onde yn é o sinal de saída e xn é o sinal de entrada. Eq. (1) pode ser escrito recursivamente como Então você sempre precisa lembrar a amostra xn-N para calcular (2). Como indicado por Conrad Turner, você pode usar uma janela exponencial (infinitamente longa), que permite calcular a saída somente da saída anterior e da entrada atual: mas esta não é uma média móvel padrão (não ponderada), mas uma média exponencial Ponderada média móvel, onde as amostras mais no passado obter um menor peso, mas (pelo menos em teoria) você nunca se esqueça nada (os pesos apenas ficar menor e menor para amostras no passado). Eu implementei uma média móvel sem memória de item individual para um programa de rastreamento GPS que eu escrevi. Eu começo com 1 amostra e dividir por 1 para obter o avg atual. Eu adiciono então uma outra amostra e divido por 2 à corrente avg. Isso continua até que eu chegar ao comprimento da média. Cada vez depois, eu adiciono na nova amostra, obter a média e remover essa média do total. Eu não sou um matemático, mas isso parecia ser uma boa maneira de fazê-lo. Eu imaginei que iria transformar o estômago de um cara de matemática real, mas, verifica-se que é uma das formas aceitas de fazê-lo. E funciona bem. Basta lembrar que quanto maior o seu comprimento, mais lento é seguir o que você deseja seguir. Isso pode não importar a maior parte do tempo, mas quando os satélites seguintes, se você é lento, a trilha poderia estar longe da posição real e vai ficar mal. Você poderia ter uma lacuna entre o sat e os pontos de arrasto. Eu escolhi um comprimento de 15 atualizado 6 vezes por minuto para obter alisamento adequado e não ficar muito longe da posição real sentado com os pontos de trilha suavizada. Respondida Nov 16 16 at 23:03 initialize total 0, count0 (cada vez vendo um novo valor Então uma entrada (scanf), um add totalnewValue, um incremento (count), uma divide average (totalcount) Todas as entradas Para calcular a média apenas nas últimas 4 entradas, seria necessário 4 variáveis ​​de entrada, talvez copiando cada entrada para uma variável de entrada mais antiga, calculando a nova média móvel como a soma das 4 variáveis ​​de entrada, dividida por 4 Bom se todos os insumos foram positivos para fazer o cálculo médio respondido Feb 3 15 at 4:06 Isso vai realmente calcular a média total e não a média móvel. Como a contagem fica maior o impacto de qualquer nova amostra de entrada torna-se ndash nitidamente pequeno Hilmar fevereiro 3 15 at 13:53 Sua resposta 2017 Stack Exchange, IncEu estou tentando calcular a média móvel de um sinal. O valor do sinal (um duplo) é atualizado em tempos aleatórios. Eu estou procurando uma maneira eficiente para calcular a sua média ponderada em tempo Ove R uma janela de tempo, em tempo real. Eu poderia fazer isso sozinho, mas é mais desafiador do que eu pensava. A maioria dos recursos que eu encontrei na internet estão calculando a média móvel do sinal periódico, mas as atualizações de minas em tempo aleatório. Alguém sabe bons recursos para que o truque é o seguinte: Você recebe atualizações em tempos aleatórios por meio de atualização void (tempo int, valor float). No entanto, você também precisa acompanhar quando uma atualização cai fora da janela de tempo, então você definir um alarme que chamado no tempo N que remove a atualização anterior de ser sempre considerado novamente na computação. Se isso acontece em tempo real, você pode solicitar o sistema operacional para fazer uma chamada para um dropoffoldestupdate método void (int time) para ser chamado em tempo N Se esta é uma simulação, você não pode obter ajuda do sistema operacional e você precisa Faça-o manualmente. Em uma simulação você chamaria métodos com o tempo fornecido como um argumento (que não se correlaciona com o tempo real). No entanto, uma suposição razoável é que as chamadas são garantidas de tal forma que os argumentos de tempo estão aumentando. Neste caso, você precisa manter uma lista ordenada de valores de tempo de alarme e, para cada atualização e chamada de leitura, você verifica se o argumento de tempo é maior que o cabeçalho da lista de alarmes. Enquanto é maior você faz o processamento relacionado com o alarme (solte a atualização mais antiga), remova a cabeça e verifique novamente até que todos os alarmes antes do tempo determinado sejam processados. Em seguida, faça a chamada de atualização. Até agora tenho assumido que é óbvio o que você faria para a computação real, mas vou elaborar apenas no caso. Eu suponho que você tem um método float read (tempo int) que você usa para ler os valores. O objetivo é tornar essa chamada o mais eficiente possível. Portanto, você não calcula a média móvel sempre que o método de leitura é chamado. Em vez disso, você precompute o valor a partir da última atualização ou o último alarme e ajustar esse valor por um par de operações ponto flutuante para conta para a passagem do tempo desde a última atualização. (Isto é, um número constante de operações excepto para talvez processar uma lista de alarmes acumulados). Esperemos que isso seja claro - este deve ser um algoritmo bastante simples e bastante eficiente. Otimização adicional. Um dos problemas restantes é se um grande número de atualizações acontecer dentro da janela de tempo, então há um longo tempo para que não há nem lê nem atualizações e, em seguida, uma leitura ou atualização vem junto. Neste caso, o algoritmo acima será ineficiente na atualização incremental do valor para cada uma das atualizações que está caindo. Isso não é necessário porque só nos preocupamos com a última atualização além da janela de tempo, por isso, se houver uma maneira de descartar eficientemente todas as atualizações antigas, isso ajudaria. Para fazer isso, podemos modificar o algoritmo para fazer uma busca binária de atualizações para encontrar a atualização mais recente antes da janela de tempo. Se houver relativamente poucas atualizações que precisam ser descartadas, então um pode atualizar incrementalmente o valor para cada atualização descartada. Mas se houver muitas atualizações que precisam ser descartadas, então um pode recalcular o valor do zero após deixar as atualizações antigas. Apêndice na Incremental Computação: Eu deveria esclarecer o que quero dizer com computação incrementais acima na frase ajustar este valor por um par de operações de ponto flutuante para dar conta da passagem do tempo desde a última atualização. Cálculo inicial não incremental: então iterar sobre datas relevantes por ordem crescente de tempo: movendo-se (sum lastupdate timesincelastupdate) windowlength. Agora, se exatamente uma atualização cai da janela, mas nenhuma nova atualização chegar, ajuste a soma como: (note que é priorupdate que tem seu timestamp modificado para iniciar o último início da janela). E se exatamente uma atualização entra na janela, mas nenhuma nova atualização cair, ajustar soma como: Como deveria ser óbvio, este é um esboço, mas esperamos que ele mostra como você pode manter a média de tal forma que é O (1) operações por atualização Sobre uma base amortizada. Mas observe otimização adicional no parágrafo anterior. Observe também problemas de estabilidade a que alude uma resposta mais velho, o que significa que os erros de ponto flutuante pode acumular-se ao longo de um grande número de tais operações incrementais de tal forma que há uma divergência entre o resultado do cálculo integral que é significativo para a aplicação. Se uma aproximação é OK e há um tempo mínimo entre as amostras, você pode tentar super-amostragem. Tenha uma matriz que represente intervalos de tempo uniformemente espaçados que são menores do que o mínimo e, em cada período de tempo, armazene a amostra mais recente que foi recebida. Quanto mais curto o intervalo, mais próxima a média será do valor verdadeiro. O período não deve ser maior do que a metade do mínimo ou há uma chance de faltar uma amostra. Respondeu Dec 15 11 at 18:12 Obrigado pela resposta. Uma melhoria que seria necessário para realmente quotcachequot o valor da média total para que don39t loop o tempo todo. Além disso, pode ser um ponto menor, mas não seria mais eficiente usar um deque ou uma lista para armazenar o valor, uma vez que assumimos que a atualização virá na ordem correta. A inserção seria mais rápida do que no mapa. Ndash Arthur 16 dez às 8:55 Sim, você poderia armazenar em cache o valor de soma. Subtraia os valores das amostras que você apaga, adicione os valores das amostras inseridas. Além disso, sim, um dequeltpairltSample, Dategtgt pode ser mais eficiente. Eu escolhi o mapa para a legibilidade, ea facilidade de invocar map :: upperbound. Como sempre, escreva o código correto primeiro, depois perfil e mude as mudanças incrementais. Ndash Rob 16 de dezembro às 15:00 Nota: Aparentemente esta não é a maneira de abordar isso. Deixando aqui para referência sobre o que está errado com esta abordagem. Verifique os comentários. UPDATED - com base no comentário Olis. Não tenho certeza sobre a instabilidade de que ele está falando embora. Use um mapa ordenado de tempos de chegada contra valores. Após a chegada de um valor adicionar a hora de chegada para o mapa ordenado, juntamente com o seu valor e atualizar a média móvel. Aviso este é pseudo-código: Lá. Não totalmente desenvolvido, mas você começa a idéia. Coisas a observar. Como eu disse o acima é pseudo código. Você precisará escolher um mapa apropriado. Não remova os pares à medida que você iterar através como você irá invalidar o iterador e terá que começar novamente. Veja Olis comentário abaixo também. Este trabalho não funciona: ele não leva em conta que proporção do comprimento da janela de cada valor existe para. Além disso, essa abordagem de adição e subtração é apenas estável para tipos inteiros, e não para flutuadores. Ndash Oliver Charlesworth Dec 15 11 em 12:29 OliCharlesworth - desculpe eu perdi alguns pontos-chave na descrição (duplo e ponderada). Eu vou atualizar. Obrigado. Ndash Dennis Dec 15 11 at 12:33 A ponderação de tempo é ainda outro problema. Mas isso não é o que eu estou falando. Eu estava me referindo ao fato de que quando um novo valor entra pela primeira vez na janela de tempo, sua contribuição para a média é mínima. Sua contribuição continua a aumentar até que um novo valor entre. Ndash Oliver Charlesworth 15 de dezembro às 12: 35 Eu sei que isso é possível com o impulso como por: Mas eu realmente gostaria de evitar usar impulso. Eu tenho googled e não encontrei qualquer exemplos adequados ou legível. Basicamente, eu quero acompanhar a média móvel de um fluxo contínuo de um fluxo de números de ponto flutuante usando os números de 1000 mais recentes como uma amostra de dados. Qual é a maneira mais fácil de conseguir isso que eu experimentei com o uso de uma matriz circular, média móvel exponencial e uma média móvel mais simples e descobriu que os resultados da matriz circular adequado às minhas necessidades. Se suas necessidades são simples, você pode apenas tentar usar uma média móvel exponencial. Simplificando, você faz uma variável de acumulador, e como seu código olha para cada amostra, o código atualiza o acumulador com o novo valor. Você escolhe um alfa constante que está entre 0 e 1 e calcula isso: Você só precisa encontrar um valor de alfa onde o efeito de uma determinada amostra dura apenas cerca de 1000 amostras. Hmm, Im realmente não tenho certeza que isso é adequado para você, agora que Ive colocá-lo aqui. O problema é que 1000 é uma janela muito longa para uma média móvel exponencial Não tenho certeza se há um alfa que iria espalhar a média nos últimos 1000 números, sem subfluxo no cálculo de ponto flutuante. Mas se você quisesse uma média menor, como 30 números ou assim, esta é uma maneira muito fácil e rápida de fazê-lo. Respondeu 12 de junho 12 em 4:44 1 em seu borne. A média móvel exponencial pode permitir que o alfa seja variável. Portanto, isto permite que ele seja usado para calcular médias de base de tempo (por exemplo, bytes por segundo). Se o tempo desde a última actualização do acumulador for superior a 1 segundo, deixe alfa ser 1.0. Caso contrário, você pode deixar alfa ser (usecs desde a última atualização1000000). Ndash jxh 12 de junho de 12 às 6:21 Basicamente eu quero acompanhar a média móvel de um fluxo em curso de um fluxo de números de ponto flutuante usando os mais recentes números de 1000 como uma amostra de dados. Observe que o abaixo atualiza o total como elementos como addedreplaced, evitando costal O (N) traversal para calcular a soma - necessária para a média - on demand. Total é feito um parâmetro diferente de T para suporte, e. Usando um longo longo quando totalizando 1000 s longos, um int para char s, ou um dobro ao total float s. Este é um pouco falho em que numsamples poderia ir passado INTMAX - se você se importa que você poderia usar um unsigned longa. Ou usar um membro de dados bool extra para gravar quando o recipiente é preenchido pela primeira vez enquanto ciclismo numsamples ao redor da matriz (melhor então renomeado algo inócuo como pos). Respondida em 12 de junho de 12 às 5:19, assume-se que o operador de quotvoid (amostra T) é realmente operador quotvoid (T amostra) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. Bem manchado. Na verdade, eu quis dizer para ser vazio operador () (T amostra), mas é claro que você poderia usar qualquer nota que você gostava. Will fix, obrigado. Ndash Tony D 8 Jun 14 às 14:27

Comments