Algoritmo de Fatoração de Fermat (FFA) em Perl
Publicado por Perfil removido (última atualização em 17/05/2012)
[ Hits: 8.737 ]
FFA: Fermat Factoring Algorithm (Algoritmo de Fatoração de Fermat)
Método de fatoração inventado por Pierre de Fermat:
Todo numero pode ser escrito como diferença de dois números elevados ao quadrado:
n = a² - b², ou n = a*a - b*b;
Esta expressão pode ser escrita como n = (a+b) * (a-b), ou n = (a+b) (a-b), onde a soma e a subtração dos valores "a" e "b" são dois fatores do número em questão.
Se n é primo, então a-b = 1 e a+b=n;
Para números com diversos fatores e divisores existem diversos "a" e "b" que satisfazem a expressão.
Este algoritmo testa em progressão diversos valores "b" em "i + j*j", ou i + j², com i=n no primeiro passo.
Se i + j*j for um quadrado perfeito, então calcula-se com base nisto os correspondentes a e b da expressão anterior, tendo-se então encontrado um fator.
Fator este que não é necessariamente um número primo.
Este programa trabalha com os fatores sendo escritos em uma lista, sendo pegos um a um até o final.
A função de fatoração retorna uma estrutura com um par de números que se multiplicados retornam o valor de entrada, ordenados em maior e menor.
No retorno, a parcela menor substitui a posição do elemento pego anteriormente e a parcela maior é inserida ao fim da lista principal.
Quando o valor menor do par é um, o valor maior é um número primo, então continua-se com o próximo elemento da lista principal, encerrando-se ao último elemento.
Por último, a lista de fatores é ordenada para apresentação.
Obs[1]: Ainda é possível melhorá-lo.
Obs[2]: Números negativos são desconsiderados para simplificação. Por enquanto.
#!/usr/bin/perl use warnings; use strict; my $VALOR = 3*5*7*3*11*31*43*31; sub fator { my $n = shift; return (-1, 1) if ($n<0); return (0, 1) if (!$n); return (1, 1) if (!($n>>1)); return (($n>>1),2) if (~$n&1); my ($i, $j, $k) = ($n, 0, 0); do { $i += $j; $k = int sqrt($i); $j += ((!$j)?1:2); } while ($i-$k*$k>0); $k += ($j-1)>>1; $n /= $k; return (($n>$k?$n:$k),($n<$k?$n:$k)); } my @fatores1 = ($VALOR); my $p = 1; foreach (@fatores1) { do { ($_, $p) = fator($_); push (@fatores1, $p) unless ($p==1); } until ($p<=1); } my @fatores2 = sort { $a <=> $b } (@fatores1); foreach (@fatores2) { print "$_ "; } print "\n";
htt[p]erl, simulador de web server
Introdução a Persistência de Estrutura de Dados em Perl
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Vou voltar moderar conteúdos de Dicas e Artigos (1)
SysAdmin ou DevOps: Qual curso inicial pra essa área? (3)
É cada coisa que me aparece! - não é só 3% (3)
Melhorando a precisão de valores flutuantes em python[AJUDA] (5)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta