Saturday 24 August 2019

Java moving average queue


Versão muito mais simples: classe pública MovingAverageInSlidingWIndow int windowsize Fila de fila int sum public MovingAverageInSlidingWIndow (int windowsize) this. windowsize windowsize this. queue novo LinkedList () this. sum 0 encontra a média móvel após inserir o item n no fluxo de dados private findMovingAverage (int N) if (queue. size () gt windowsize - 1) soma sum - queue. poll () queue. offer (n) soma soma n retorno (duplo) soma queue. size () public static void main Windowsize 3 MovingAverageInSlidingWIndow m novo MovingAverageInSlidingWIndow (windowsize) para (int i 1 i lt 20 i) System. out. println (quotAfter Adicionando quot i quot para a fila: Average é: quot m. findMovingAverage (i)) Podemos simplesmente persistir o Soma atual de elementos na fila na variável global. Assim, reduzindo a computação no método next (). Public class MovingAverage LinkedList fila int size int sum 0 mantém sum a fila Inicialize sua estrutura de dados aqui. Public MovingAverage (int size) this. queue novo LinkedList () this. size tamanho public double next (int val) queue. offer (val) soma val if (queue. size () gtthis. size) sum - queue. poll () Implementando uma fila FIFO de comprimento fixo em Java Ao trabalhar com dados de séries temporais, muitas vezes é necessário calcular somas de números consecutivos para um período de tempo predeterminado. Imagine, por exemplo, calcular uma média móvel com um tamanho fixo. Vamos olhar para uma série de tempo muito simples. Supondo que uma média móvel de comprimento 4 resulta na seguinte matriz: A fórmula para uma média móvel de comprimento 4 é assim: MA t (Soma de todos os elementos de t-3 a t) 4 Como implementaríamos isso de forma eficiente no código Java The Problema é que precisamos calcular a Soma na fórmula para cada média móvel. Claro que é possível sempre reiterar sobre todos os números no período de tempo atual para fazê-lo, mas isso é desnecessariamente lento. Em vez disso, podemos simplesmente subtrair o último elemento no período de tempo e adicionar o mais novo a Sum. Desta forma, podemos economizar um número significativo de computações desnecessárias. Ainda temos que acompanhar o que realmente são os elementos antigos e novos. Temos de armazenar esses números em algum lugar. Uma estrutura de dados apropriada seria uma fila de números first-in-first-out (FIFO). Mas como exatamente uma fila FIFO pode ser implementada em uma linguagem de programação (não-funcional) como Java? A primeira idéia é tipicamente usar uma implementação baseada em array e mudar a posição de elementos na matriz criando repetidamente cópias ligeiramente deslocadas de A matriz. No exemplo acima, precisaríamos criar uma nova matriz cinco vezes, uma vez para cada nova soma que está sendo calculada. Isto é, naturalmente, muito ineficiente, porque a criação de uma matriz na memória é relativamente lento. Implementações baseadas em classes como java. util. ArrayList ou java. util. Vector já são muito melhores, porque internamente eles dependem de matrizes e índices mais longos. Ainda assim, esta não é a melhor solução, uma vez que os índices internos se movem para fora dos limites da matriz interna, uma nova cópia da matriz interna deve ser criada. Uma alternativa típica para implementar filas FIFO está, portanto, usando uma lista vinculada: A vantagem é óbvia, não mais copiar ou recriar arrays na memória. Tudo o que temos a fazer é manipular alguns ponteiros. Claro que perdemos a vantagem de avaliar diretamente um elemento na fila por índice, mas para o nosso propósito - calculando médias móveis - isso é algo que não queremos fazer de qualquer maneira. Ontem, de repente me ocorreu que há realmente uma alternativa ainda melhor se o comprimento da fila é fixo (como no nosso exemplo). Podemos efetivamente usar um anel. Adicionar um novo número à fila e soltar o mais antigo é o mesmo que simplesmente substituir o elemento mais antigo neste anel por um novo. Internamente, podemos usar novamente uma matriz de um comprimento fixo em combinação com um índice rotativo. Este é o aspecto do código em Java. Primeiro, vamos criar nossa própria interface de fila: Esta interface diverge um pouco da fornecida nas bibliotecas Java, mas isso não é importante por enquanto. Em seguida, a implementação da nossa fila: A fila quotrollsquot através do anel. Adicionar um novo elemento na cabeça da fila remove automaticamente o elemento mais antigo da fila - não é necessário copiar arrays ou redefinir referências de objeto. Ao contrário das listas vinculadas, podemos acessar cada elemento do anel diretamente com o método get. Finalmente, podemos criar uma subclasse do nosso objeto de fila que rodará graciosamente à medida que novos valores são adicionados ao queering. Podemos usar a classe agora. O comprimento da média móvel é inicialmente definido através do comprimento da matriz dada ao seu constructor. I necessidade de acompanhar os últimos 7 dias de trabalho horas em um loop de leitura de arquivo plano. Seu ser usado para medir fatigueability de rosters do trabalho. Agora eu tenho algo que funciona, mas parece bastante detalhado e não tenho certeza se há um padrão que é mais sucinto. Atualmente, eu tenho uma classe Java com uma matriz estática para armazenar os últimos dados x dias, então como eu leio através do arquivo, eu cortar o primeiro elemento e mover os outros 6 (por uma semana rodando total) de volta por um. O processamento dessa matriz estática é feito em seu próprio método ie. Minha pergunta: esta é uma abordagem de design razoável, ou há algo de cegueira óbvia e simples para fazer esta tarefa Obrigado rapazes pediu Aug 30 11 at 14:33 Thanks alot guys: I39ve tem a mensagem: use um objeto de nível mais alto e explorar o Métodos relevantes ou um tampão circular. Grandes respostas, todas elas. Quando você pensa sobre isso, você sempre precisa de acesso a toda a matriz para que você possa se livrar da primeira entrada - que eu wasn39t 100 certeza de no meu próprio. I39m aliviado que eu hadn39t perdeu um forro 1 e foi basicamente em uma pista razoável, se não eficiente e concisa Isso é o que eu adoro sobre este site: de alta qualidade, respostas relevantes de pessoas que sabem o seu sht. Ndash Pete855217 Aug 30 11 at 15:05 Por que você inicializar runningTotal para null Qual é o seu tipo Onde é declarado Faria bem se você colocar alguns exemplos de código que se assemelham ao código Java real. Seguindo em frente, minha crítica seria a seguinte: a sua função faz muito. Uma função ou método deve ser coeso. Mais apropriadamente, eles deveriam fazer uma coisa e uma coisa só. Pior ainda, o que acontece no seu loop for quando x 5 Você copia runningTotal6 em runningTotal5. Mas então você tem duas cópias do mesmo valor na posição 5 e 6. Em seu projeto, sua função movesshuffles os itens em sua matriz calcula o total imprime coisas para erro padrão retorna o total Ele faz muito. Minha primeira sugestão é não mover coisas ao redor da matriz. Em vez disso, implementar um buffer circular e usá-lo em vez da matriz. Simplificará seu projeto. Minha segunda sugestão é dividir as coisas em funções que são coesas: ter uma estrutura de dados (um buffer circular) que permite adicionar a ele (e que descarta a entrada mais antiga sempre que atingir sua capacidade.) Ter a estrutura de dados implementar um Interator tem uma função que calcula o total no iterador (você não se importa se você está calculando o total de uma matriz, lista ou bufer circular.) Não chamá-lo total. Chamá-lo de soma, que é o que você está computando. Isso é o que fazer :) That39s grande informação luis, no entanto lembre-se esta função é uma pequena parte da funcionalidade da classe, e seria exagero para adicionar muito código para torná-lo perfeito. Você está tecnicamente correto, e eu entendo que meu código faz muito 39, mas ao mesmo tempo às vezes é melhor errar do lado do código menor, mais claro do que ir para a perfeição. Dado o meu Java habilidades, mesmo fazendo o pseudocódigo que você descreve compilação teria me golpe meu orçamento sobre este (), mas obrigado pela descrição clara. Ndash Pete855217 Aug 31 11 at 2:23 Hmmm, não é sobre a perfeição, mas sobre as práticas industriais estabelecidas que temos conhecimento para as últimas 3 décadas. Código limpo é sempre um que é particionado. Temos décadas de evidências que indicam que este é o caminho a percorrer no caso geral (em termos de custo-eficiência, redução de defeitos, compreensão, etc.). A menos que seja um código descartável para um tipo único de coisa. Nunca é custoso fazer isso quando se inicia qualquer análise de problemas desta maneira. Codificação 101, quebrar o problema eo código segue, nem overkill nem difícil) ndash luis. espinal Aug 31 11 at 15:55 Sua tarefa é muito simples ea abordagem que você adotou é certamente bom para o trabalho. No entanto, se você quiser usar um projeto melhor, você deve se livrar de todo esse movimento número você melhor usar uma fila FIFO e fazer bom uso de push e pop métodos dessa forma o código não vai refletir qualquer movimento de dados, apenas as duas ações lógicas De novos dados e remover dados com mais de 7 dias. Respondeu 30 Ago 11 at 14:49

No comments:

Post a Comment