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 de calcular a sua média ponderada em tempo sobre 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 o que o truque é o seguinte: Você recebe atualizações em tempos aleatórios através de void update (tempo int, valor float). No entanto, você também precisa acompanhar quando uma atualização cai fora da janela de tempo, então você define um alarme que chamado no tempo N que remove a atualização anterior de ser sempre considerado novamente na computação. Se isso acontecer em tempo real, você pode solicitar que o sistema operacional faça uma chamada para um método void dropoffoldestupdate (int time) para ser chamado no momento 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 chamada de atualização e leitura, verifique se o argumento de tempo é maior que o cabeçalho da lista de alarmes. Embora seja maior você faz o processamento relacionado com o alarme (deixe cair 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á ineficaz na atualização incremental do valor para cada uma das atualizações que está caindo. Isso não é necessário, porque nós só nos preocupamos com a última atualização além da janela de tempo, então se houver uma maneira eficiente de deixar todas as atualizações mais antigas, que 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 sobre Computação Incremental: Eu deveria esclarecer o que eu quero dizer por computação incremental acima na sentença tweak este valor por um par de operações de ponto flutuante para explicar a passagem do tempo desde a última atualização. Cálculo inicial não incremental: então iterar sobre as atualizações relevantes por ordem crescente de tempo: movimentação (sum lastupdate timesincelastupdate) / windowlength. Agora, se exatamente uma atualização cair 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 cai, ajuste a soma como: Como deve ser óbvio, este é um esboço aproximado, mas espero que ele mostra como você pode manter a média tal que é O (1) operações por atualização Sobre uma base amortizada. Mas observe otimização adicional no parágrafo anterior. Observe também as questões de estabilidade mencionadas em uma resposta mais antiga, o que significa que os erros de ponto flutuante podem se acumular em um grande número dessas operações incrementais, de modo que há uma divergência em relação ao resultado da computação completa que é significativa para a aplicação. Se uma aproximação é OK e há um tempo mínimo entre as amostras, você poderia tentar super-amostragem. Tenha uma matriz que represente intervalos de tempo uniformemente espaçados que sejam mais curtos que o mínimo, e em cada período de tempo armazene a amostra mais recente que foi recebida. Quanto menor o intervalo, mais próxima será a média do valor real. O período não deve ser maior que a metade do mínimo ou há uma chance de faltar uma amostra. Respondeu Dec 15 11 at 18:12 respondeu Dec 15 11 at 22:38 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 e, em seguida, perfile e mude as alterações incrementais. Ndash Rob Dec 16 11 at 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 que ele está falando embora. Use um mapa ordenado de tempos de chegada contra valores. Na chegada de um valor adicione a hora de chegada ao mapa ordenado junto com seu valor e atualize 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, 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 em tempo). 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 de 11 em 12: 35 Eu sei que isto é achievable com 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 em andamento de um fluxo de números de ponto flutuante usando os mais recentes números de 1000 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 só dura 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 estenderia a média nos últimos 1000 números, sem subfluxo no cálculo do 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, isso 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ção / 1000000). Ndash jxh Jun 12 12 at 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 adicionado / substituído, 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. Isso é um pouco falho em que numsamples poderia ir passado INTMAX - se você se importa que você poderia usar um unsigned longo longo. Ou usar um membro de dados bool extra para gravar quando o recipiente é preenchido pela primeira vez enquanto ciclismo numsamples em torno 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 quotvoid (amostra T) é, na verdade, operador quotvoid (T amostra) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. Bem manchado. Na verdade, eu quis dizer para ser void operador () (T amostra), mas é claro que você poderia usar qualquer nota que você gostava. Vai corrigir, obrigado. Ndash Tony D Jun 8 14 at 14: 27Quero desenvolver cálculo para a média móvel preço das ações. Mas muitos cálculos complexos foram planejados mais tarde. Meu primeiro passo para saber como calcular a média móvel de forma eficiente. Eu preciso saber como tomar a entrada e retorno de saída de forma eficiente. Considerado data e preço de entrada. Data, Preço e Média Móvel. Se eu tiver 500 registros e eu quero calcular média móvel por 5 dias o que é a maneira effient em vez de ir para a frente e para trás na matriz de data e preço novamente sugerir o que é a melhor maneira de receber entrada (ArrayList, Table, array Etc) e retorno de saída. Nota: MA de hoje de 5 dias será média dos últimos 5 dias incluindo preço de hoje. Ontem MA será média dos últimos 5 dias de ontem. Eu quero manter os dias para ser flexível em vez de 5 ele poderia ser 9, 14, 20 etc Se você precisa de cálculo simples sem o seu esforço do que você pode usar TA-Lib. Mas se você quiser que seu cálculo seja mais eficiente do que o TA-Lib, então você pode criar seu próprio indicador técnico. TA-Lib é grande, mas o problema é que esta biblioteca tem apenas métodos estáticos. Isso significa que quando você precisa calcular os valores da matriz SMA com base em barras de preço de 500, então você enviará toda a matriz de barras e ele retornará matriz de valores SMA. Mas se você receber novo valor 501-st, então você deve enviar novamente toda a matriz e TA-Lib novamente calculará e retornará SMA matriz de valores. Agora imagine que você precisa desse indicador no feed de preços reais, e para cada mudança de preço você precisa de um novo valor indicador. Se você tem um indicador não é um grande problema, mas se você tiver centenas de indicadores de trabalho, que poderia ser um problema de desempenho. Eu estava em tal situação e começar a desenvolver indicadores em tempo real que são eficientes e fazer cálculos adicionais para a nova barra de preço ou para a barra de preço alterado apenas. Unfortunatelly Eu nunca precisei SMA indicador para os meus sistemas de negociação, mas eu tenho tal para EMA, WMA, AD, e outros. Um desses indicadores AD é publicado no meu blog e você pode ver a partir daí o que é a estrutura básica da minha classe indicador em tempo real. Espero que você vai precisar de pequenas mudanças para implementar SMA indicador, porque é um dos mais simples. A lógica é simples. Para calcular SMA tudo que você precisa é n últimos preços. Assim classe instância terá coleta de preços, que irá armazenar manter apenas último n número de preços como SMA é definido (no seu caso 5). Então, quando você tem um novo bar, você removerá o mais antigo e adicionará um novo e criará um cálculo. Quinta-feira, 10 de abril de 2008 16:04 Todas as respostas Há uma biblioteca chamada TA-Lib que faz tudo isso para você e é de código aberto. Tem cerca de 50 indicadores eu acho. Weve usou-o no ambiente da produção e é muito eficiente e realible. Você pode usá-lo em C, Java, C, etc Se você precisa de um cálculo simples sem o seu esforço do que você pode usar TA-Lib. Mas se você quiser que seu cálculo seja mais eficiente do que o TA-Lib, então você pode criar seu próprio indicador técnico. TA-Lib é grande, mas o problema é que esta biblioteca tem apenas métodos estáticos. Isso significa que quando você precisa calcular os valores da matriz SMA com base em barras de preço de 500, então você enviará toda a matriz de barras e ele retornará matriz de valores SMA. Mas se você receber novo valor 501-st, então você deve enviar novamente toda a matriz e TA-Lib novamente calculará e retornará SMA matriz de valores. Agora imagine que você precisa desse indicador no feed de preços reais, e para cada mudança de preço você precisa de um novo valor indicador. Se você tem um indicador não é um grande problema, mas se você tiver centenas de indicadores de trabalho, que poderia ser um problema de desempenho. Eu estava em tal situação e começar a desenvolver indicadores em tempo real que são eficientes e fazer cálculos adicionais para a nova barra de preços ou para a barra de preço alterado apenas. Unfortunatelly Eu nunca precisei SMA indicador para os meus sistemas de negociação, mas eu tenho tal para EMA, WMA, AD, e outros. Um desses indicadores AD é publicado no meu blog e você pode ver a partir daí o que é a estrutura básica da minha classe indicador em tempo real. Espero que você vai precisar de pequenas mudanças para implementar SMA indicador, porque é um dos mais simples. A lógica é simples. Para calcular SMA tudo que você precisa é n últimos preços. Assim classe instância terá coleta de preços, que irá armazenar manter apenas último n número de preços como SMA é definido (no seu caso 5). Então, quando você tem um novo bar, você removerá o mais antigo e adicionará um novo e criará um cálculo. Quinta-feira, 10 de abril de 2008 16:04 Eu calcularia a média móvel no banco de dados por meio de um procedimento armazenado ou em um cubo. Você já olhou no Analysis Services, ele tem a capacidade de calcular médias móveis. Quinta-feira, 10 de abril de 2008 16:05 Sim. TA-LIB é bom, mas pode não ser adequado para mim. Quando eu adicionar novo valor ou valor atualizado para o histórico de registros vou fazer o cálculo em uma função separada apenas para essa nova cotação e armazená-lo no banco de dados. Estou planejando atualizar a cotação a cada hora. Eu preciso fazer cerca de 25 a 30 indicadores técnicos para 2200 ações. Quinta-feira, 10 de abril de 2008 17:51 Tempo de execução de uma chamada TA-Lib em uma matriz de 10000 elementos leva cerca de 15 milissegundos (em um Intel Core Duo 2.13 Ghz). Esta é a média de todas as funções. Entre os mais rápidos, SMA leva menos de 2,5 milissegundos. O mais lento, HTTRENDMODE, leva 450 milissegundos. Com menos elementos é mais rápido. SMA leva cerca de 0,22 milissegundos para 1000 elementos de entrada. O ganho de velocidade é quase linear (a sobrecarga de realização da chamada de função é desprezível). No contexto de sua aplicação, TA-Lib é muito improvável que seja seu gargalo para desempenho de velocidade. Também eu geralmente não recomendo essa solução nquot quotlast. Leia abaixo para mais detalhes. Primeiro, uma correção para Boban. s declaração Todas as funções em TA-Lib também pode calcular um único último valor usando um mínimo de quotlast nquot elementos. Você pode ter uma matriz de tamanho 10000, ter dados inicializar apenas para os primeiros 500 elementos, adicionar um elemento e chamar TA-Lib para calcular o SMA somente para o novo elemento. TA-Lib vai olhar para trás não mais do que o necessário (se SMA de 5, em seguida, TA-Lib irá calcular um único SMA usando os últimos 5 valores). Isso é possível com o parâmetro startIdx e endIdx. Você pode especificar um intervalo a ser calculado ou um único valor. Neste cenário, você faria startIdx endIdx 500 para calcular o elemento 501st. Por que essa solução quotlast nquot é potencialmente perigosa para alguns Independentemente da escolha da solução Boban. s ou TA-Lib consideram que usar um pequeno número finito de dados passados não funcionará bem com a maioria das funções TA. Com SMA, é óbvio que você só precisa de elemento n para calcular uma média sobre o elemento n. Não é tão simples com EMA (e muitas outras funções TA). O algo geralmente depende do valor anterior para calcular o novo valor. A função é recursiva. Isso significa que todos os valores passados influenciam os valores futuros. Se você decidir quotlimitquot seu algo para usar apenas uma pequena quantidade de passado n valor, você não obterá o mesmo resultado como alguém que calcula sobre um grande número de valores passados. A solução é um compromisso entre velocidade e precisão. Muitas vezes discuti isso no contexto de TA-Lib (chamo-o o período quotunstable na documentação e fórum). Para mantê-lo simples, minha recomendação geral é se você não pode fazer a diferença entre um algo com uma resposta de impulso finito (FIR) de um algo com uma resposta de impulso infinita (IIR), você será mais seguro para calcular todos os dados que você tem disponível. TA-Lib especifica no código qual das suas funções tem um período instável (IIR). Eu não estou certo da solução correta, mas uma vez que somar a média de cada amostra iria introduzir uma boa quantidade de erro de arredondamento. Hmm. Gostaria de saber se seperating a parte fracionária de toda a parte iria ajudar. Divida a parte inteira de cada número pela contagem. Manter três somas correntes: 1) A média das partes inteiras, 2) O restante de cada divisão, e 3) A parte fracionária de cada número. Cada vez que a parte inteira de um número é dividida, o resultado da parte inteira é adicionado à soma corrente média e o restante é adicionado à soma corrente restante. Quando a soma corrente restante obtém um valor maior ou igual à contagem, a sua divisão pela contagem com o resultado da peça inteira adicionada à soma média corrente e o restante adicionado à soma restante em curso. Também, em cada cálculo, a parte fracionária é adicionada à soma de corrida fracionária. Quando a média é terminada, a soma corrente restante é dividida pela contagem e o resultado é adicionado à soma média corrente como um número flutuante. Por exemplo: Agora o que fazer com a soma de execução fracionada. O perigo de estouro é muito menos provável aqui, embora ainda possível, então uma maneira de lidar com isso seria dividir a soma de execução fracionária pela contagem no final e adicioná-lo ao nosso resultado: Uma alternativa seria verificar a execução fracionária Soma em cada cálculo para ver se ele é maior ou igual a contar. Quando isso acontece, basta fazer a mesma coisa que fazemos com o restante executando soma. Excelente Jomit Vaghela 6-Mar-07 20:00 Eu gostei do que você disse pequenos trabalhos rapidamente se transformar em grandes empregos. Pensar em otimização durante a codificação é uma boa prática. Grande esforço e explicação, Médias / Média média móvel simples / Média móvel simples Você é encorajado a resolver esta tarefa de acordo com a descrição da tarefa, usando qualquer idioma que você conheça. Calculando a média móvel simples de uma série de números. Criar uma função stateful / classe / instância que leva um período e retorna uma rotina que leva um número como argumento e retorna uma média móvel simples de seus argumentos até agora. Uma m�ia m�el simples �um m�odo para calcular uma m�ia de um fluxo de n�eros calculando apenas a m�ia dos �timos n�eros de 160 P 160 a partir do fluxo 160, em que 160 P 160 �conhecido como o per�do. Ele pode ser implementado chamando uma rotina de iniciação com 160 P 160 como argumento, 160 I (P), 160 que deve retornar uma rotina que, quando chamada com membros individuais, sucessivos de um fluxo de números, calcula a média de Para), os últimos 160 P 160 deles, vamos chamar este 160 SMA (). A palavra 160 estado 160 na descrição da tarefa refere-se à necessidade de 160 SMA () 160 lembrar determinadas informações entre as chamadas para ele: 160 O período, 160 P 160 Um recipiente ordenado de pelo menos os últimos 160 P 160 números de cada um dos Suas chamadas individuais. Stateful 160 também significa que chamadas sucessivas para 160 I (), 160 o inicializador, 160 devem retornar rotinas separadas que não 160 não compartilham o estado salvo para que possam ser usadas em dois fluxos de dados independentes. Pseudo-código para uma implementação de 160 SMA 160 é: Esta versão usa uma fila persistente para conter os valores p mais recentes. Cada função retornada de init-moving-average tem seu estado em um átomo contendo um valor de fila. Esta implementação usa uma lista circular para armazenar os números dentro da janela no início de cada ponteiro de iteração refere-se à célula de lista que mantém o valor apenas movendo para fora da janela e para ser substituído com o valor apenas adicionado. Usando um fechamento editar Atualmente este sma não pode ser nogc porque ele aloca um encerramento no heap. Alguma análise de escape pode remover a alocação de heap. Usando uma edição de estrutura Esta versão evita a alocação de heap do fechamento mantendo os dados no quadro de pilha da função principal. Mesmo resultado: Para evitar que as aproximações de ponto flutuante sigam se acumulando e crescendo, o código poderia executar uma soma periódica em toda a matriz de filas circulares. Esta implementação produz dois estados de compartilhamento de objetos (função). É idiomático em E separar a entrada da saída (ler a partir da escrita) em vez de combiná-los em um objeto. A estrutura é a mesma que a implementação do Desvio PadrãoE. O programa elixir abaixo gera uma função anônima com um período embutido p, que é usado como o período da média móvel simples. A função de execução lê entrada numérica e passa para a função anônima recém-criada e, em seguida, inspeciona o resultado para STDOUT. A saída é mostrada abaixo, com a média, seguida pela entrada agrupada, formando a base de cada média móvel. Erlang tem fechamentos, mas variáveis imutáveis. Uma solução então é usar processos e uma simples mensagem passando API baseada. As linguagens de matriz têm rotinas para calcular os avarages deslizando para uma determinada seqüência de itens. É menos eficiente para loop como nos comandos a seguir. Solicita continuamente uma entrada I. Que é adicionado ao final de uma lista L1. L1 pode ser encontrado pressionando 2ND / 1, e a média pode ser encontrada em List / OPS Pressione ON para terminar o programa. Função que retorna uma lista contendo os dados médios do argumento fornecido Programa que retorna um valor simples em cada invocação: list é a média da lista: p é o período: 5 retorna a lista média: Exemplo 2: Usando o programa movinav2 (i , 5) - Inicializando o cálculo da média móvel e definindo o período de 5 movinav2 (3, x): x - novos dados na lista (valor 3), e o resultado será armazenado na variável x e exibido movinav2 (4, x) : X - novos dados (valor 4), eo novo resultado será armazenado na variável x, e exibido (43) / 2. Descrição da função movinavg: variável r - é o resultado (a lista média) que será retornada variável i - é a variável de índice, e aponta para o fim da sub-lista a lista sendo calculada a média. Variável z - uma variável auxiliar A função usa a variável i para determinar quais valores da lista serão considerados no cálculo da média seguinte. Em cada iteração, a variável i aponta para o último valor na lista que será utilizado no cálculo médio. Portanto, só precisamos descobrir qual será o primeiro valor na lista. Geralmente bem tem que considerar p elementos, então o primeiro elemento será o indexado por (i-p1). No entanto, nas primeiras iterações, esse cálculo será normalmente negativo, de modo que a seguinte equação evitará índices negativos: max (i-p1,1) ou, arranjar a equação, max (i-p, 0) 1. Mas o número de elementos nas primeiras iterações também será menor, o valor correto será (índice final - índice de início 1) ou, arranjar a equação, (i - (max (ip, 0) 1) e então , (I-max (ip, 0)). A variável z detém o valor comum (max (ip), 0) então o beginindex será (z1) e os numberofelements serão (iz) mid (list, z1, iz) retornará a lista de valor que será a soma média .) Irá somá-los soma (.) / (Iz) ri irá média deles e armazenar o resultado no lugar apropriado na lista de resultados Usando um fecho e criando uma função
No comments:
Post a Comment