Pessoal, estou fazendo a média de leituras de um sensor mas queria fazer uma média diferente.
A média que faço atualmente, ele pega x leituras e faz a média e depois mais x leituras e faz outra média... fazendo medidas em blocos de x leituras.
Como eu poderia fazer médias gradativas e não em blocos, ou seja, faço X leituras e tiro a média, depois eu adiciono 1 leitura nova e retiro uma leitura velha e tiro mais uma média.... Entendeu?
Exemplificando:
Atualmente leio de 1 a 10 e tiro a média, depois de 11 a 20 e tiro outra média( blocos de médias)
Eu quero ler de 1 a 10 e tirar a média, depois de 2 a 11 e outra média, depois de 3 a 12 e mais uma média.
Acredito que tenha como, mas como?
Obrigado.
Tags:
Vc poderia ter um array de resultados e um contador que diga qual valor vai ser sobrescrito.
Cada vez que vem um novo valor vc escreve na posicao indicada por ele e incrementa. Se ele for 10 vc zera.
Assim escreve nas posicoes de 0 a 9.
Soma tudo e divide por 10 depois eh a media obtida a cada novo ciclo e nao a cada 10 ciclos.
Gente organizada iria querer fazer um "for" pra puxar os resultados e colocar o novo no final, mas para um simples calculo de media nao faz diferença alguma, no ciclo sempre o desprezado vai ser o mais velho automaticamente, isso que importa.
Você poderia fazer uma coisa super simples
(Média * K + Valor Atual)/(K+1) = Média
Mas se você realmente quiser fazer isso o que você escreveu, basta ter um vetor e um índice i que guarda a posição a ser sobrescrita, depois fazer o somatórios de todos os valores do vetor e dividir pelo numero de valores, igual ao que o Eduardo explicou.
float aValor[5];
int amostrasValor = 0;
int tAmostras = 5;
float calculaMedia(float Valor)
{
if (amostrasValor < tAmostras)
{
aValor[amostrasValor] = Valor;
amostrasValor++;
return Valor;
}
else
{
float media = aValor[0];
for (int i = 1; i < tAmostras; i++)
{
media = media + aValor[i];
aValor[i - 1] = aValor[i];
}
aValor[tAmostras - 1] = Valor;
media = media / tAmostras;
return media;
}
}
Você pode modificar, para ele calcular a média, antes de completar o array, é só modificar na função, eu retorno o valor lido, até completar e começar a fazer a média.
Opa!!! Valeu pessoal. Agradeço a TODOS pela ajuda.
Chegando em casa vou botar para funcionar.
OBRIGADO
Funcionou?
Pelo que entendi o teu problema é manter uma média das últimas n leituras. Pra isso vc precisa ter essas leituras armazenadas em alguma estrutura e para este caso, a estrutura mais eficiente seria o buffer circular. Isso te permitiria usar um array para as medidas e nunca precisar percorrer o array seja pra adicionar ou retirar medidas ou mesmo pra calcular a média atual. Com o algoritmo certo, seria só uma questão de retirar a medida mais antiga da média e acrescentar a mais recente.
Um buffer circular é bem simples de operar e é muito eficiente. Abaixo to postando o código básico de um buffert circular para armazenar 10 valores inteiros. Eu faria isso usando uma classe, mas usando funções "soltas" acho que é mais facil de entender.
Note que em nenhum momento o array precisa ser percorrido. Esse detalhe pode não fazer tanta diferença com um buffer de 10 posições, mas quando o buffer tem milhares de itens isso faz muita diferença no desempenho do programa.
// Tamanho do buffer circular
#define buffSize 10
// buffer circular
int cBuf[buffSize];
// variáveis de controle
int firstItem = 0; // indice do primeiro item (o mais antigo)
int nextPos = 0; // índice da próxima posição livre (onde será colocado o próximo item)
int items = 0; // quantidade atual de itens no buffer
int itemsSum = 0; // soma de todos os itens
// zera o buffer
void clearBuff()
{
firstItem = 0;
nextPos = 0;
items = 0;
itemsSum = 0;
}
// Retira o primeiro item do buffer e da soma
// retorna o item retirado
int getFirst()
{
if(!items) return 0; // Se o buffer está vazio retorna sem fazer nada
// recupera o item mais antigo
int item = cBuf[firstItem];
// retira ele da soma geral
itemsSum-= item;
// atualiza o índice do primeiro item usando incremento circular
firstItem= (firstItem+1) % buffSize;
// atualiza o contador de itens;
items--;
// retorna o dito cujo
return item;
}
// adiciona um item no final do buffer e na soma geral
void addItem(int item)
{
if(items>=buffSize) // se o buffer está cheio
{
getFirst(); // remove o item mais antigo
}
// armazena o novo item no buffer
cBuf[nextPos]= item;
// atualiza a proxima posição livre
nextPos= (nextPos+1) % buffSize; // incremento circular: volta a zero qdo chega a 9
// acrescenta o item na soma geral
itemsSum+= item; //
// atualiza o contador de itens;
items++;
}
// retorna a média atual
float bufMedia()
{
if(!items) // nenhum item no buffer
return 0;
else
return (float)itemsSum/items; // média
}
Eu preciso de algo semelhante:
Faço a primeira leitura do sensor e após a segunda leitura, ele calcula a média entre as duas. Após a terceira leitura, ele calcula a média entre a terceira leitura e a média anterior... isso até um determinado horário (possuo RTC), depois ele zera as médias e começa tudo de novo a partir da próxima leitura. Isso é possível???
Bem-vindo a
Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)
© 2024 Criado por Marcelo Rodrigues. Ativado por