Por que o 2 é tãoproblemático na prática
O único número par e primo é 2. É tudo o que você precisa saber teoricamente. Na prática, isso causa confusão constante em sistemas que assumem implicitamente que primos são ímpares. Eu já vi código quebra porque alguém escreveu uma condição do tipo "se n > 2 e n é ímpar, então é primo", o que parece sensato até você tentar usar para gerar chaves criptográficas pequenas.único número par e primo: o que todo mundo esquece
Quando se trata de algoritmos de teste de primalidade, o 2 aparece como caso especial em praticamente toda implementação que eu já encontrei. O teste de divisibilidade por 2 é trivial, mas os algoritmos mais eficientes — trial division otimizado, Sieve de Eratóstenes, até mesmo tests probabilísticos como Miller-Rabin — tratam o 2 separadamente desde o início. Isso não é por preguiça. É porque todo primo depois do 2 é obrigatoriamente ímpar, o que permite otimizações significativas. No Sieve de Eratóstenes, por exemplo, você inicia marcando múltiplos a partir de 3, pulando todos os pares. O 2 precisa ser incluído manualmente no resultado final. Se você esquecer, seu sieve retorna uma lista que começa com 3, 5, 7... e parece funcionar perfeitamente até alguém testar com n=2.
O problema que eu enfrentei
Eu estava implementando um gerador de números primos para um sistema de criptografia caseiro há alguns anos. O código funcionava bem para números grandes, mas falhava silenciosamente em gerações menores. O diagnóstico levou horas. O problema estava numa função de geração de chave RSA simplificada que escolher primos aleatórios de 8 bits. O 2 podia ser selecionado, e como meu teste de primalidade tratava 2 como caso à parte de forma inconsistente, às vezes ele era rejeitado e às vezes aceito, criando uma distribuição enviesada. A solução foi simples: trate o 2 explicitamente no início de qualquer função de teste de primalidade. Primeiro verifique se n == 2 e retorne verdadeiro. Depois verifique se n é par e retorne falso. Só então prossiga com o resto do algoritmo. Isso resolveu o problema imediatamente e eliminatei um bug que poderia ter sido catastrófico em produção.
Como verificar se um número é primo corretamente
Aqui está o que eu recomendo na prática, baseado em implementação real e não em teoria de livro didático:
function isPrime(n) {
if (n === 2) return true;
if (n < 2 || n % 2 === 0) return false;
for (let i = 3; i * i = n; i += 2) {
if (n % i === 0) return false;
}
return true;
}
Os dois primeiros if's são cruciais. Eles capturam o único número par e primo antes de qualquer loop ser executado. Sem eles, você precisa confiar que o loop vai funcionar corretamente para n=2, o que depende da sua lógica de condição de parada. Alguns desenvolvedores escrevem loops que começam em 3 e verificam i*i <= n, o que funciona para 2 porque 3*3 > 2, mas isso é frágil e depende de detalhes de implementação. Para Sieve de Eratóstenes, a abordagem padrão é:
👉 Clique no botão abaixo para saber mais sobre o assunto!
function sieve(limit) {
if (limit < 2) return [];
const isComposite = new Array(limit + 1).fill(false);
const primes = [2];
for (let i = 3; i <= limit; i += 2) {
if (!isComposite[i]) {
primes.push(i);
for (let j = i * i; j = limit; j += 2 * i) {
isComposite[j] = true;
}
}
}
return primes;
}
Note que o 2 é adicionado manualmente e o loop só processa ímpares. O step dentro do loop interno também é 2*i (que é par), mantendo apenas números ímpares compostos marcados. Isso corta o trabalho pela metade comparado a uma implementação ingênua.
Armadilhas comuns
A primeira armadilha é assumir que primos são todos ímpares. Isso leva a código que falha discretamente para n=2 e para funções que dependem da propriedade "ímpar" de primos para otimizações. A segunda armadilha é mais sutil: em contextos criptográficos, escolher primos uniformemente de um intervalo que inclui o 2 pode criar vetores de ataque. Em gerar um primo de k bits para RSA, você deve garantir que o primo seja significativamente maior que 2, caso contrário a segurança cai drasticamente. Um primo de 1 bit (que é 2) não oferece nenhuma segurança. Outro ponto que passei despercebido por muito tempo: o 2 é o único primo onde a propriedade de ser ímpar falha. Muitas provas e lemas em teoria dos números assumem p é um primo ímpar, e aplicar esses resultados ao 2 sem verificar leva a erros. Por exemplo, o pequeno teorema de Fermat funciona para p=2, mas algumas formulações que usam raízes quadradas residuais ou critérios de Euler exigem p ímpar.
Quando o 2 é problema e quando é solução
Em criptografia, o 2 raramente é útil como primo de escolha. Chaves RSA modernas usam primos de 1024 a 4096 bits. O 2 é irrelevante nesse contexto. Porém, em hashing e estruturas de dados, propriedades relacionadas ao 2 são frequentemente exploradas de forma útil. Tabelas hash com tamanho potência de 2, por exemplo, usam máscaras de bits em vez de operações de módulo, o que é muito mais rápido. Já em algoritmos numéricos, o fato de que 2 é o único primo par significa que divisibilidade por 2 é um caso especial que pode ser verificado em O(1) com uma operação de bitwise AND (n & 1 === 0), enquanto divisibilidade por outros primos requer módulo. Essa diferença de custo é significativa em loops apertados que rodaram bilhões de vezes.
Se você estiver construindo algo que precisa de primos frequentemente e quer performance máxima, considere pré-computar uma tabela de primos até um certo limite usando o Sieve e consultar essa tabela para números pequenos. Para números maiores, use Miller-Rabin com bases fixas conhecidas. O caso do 2 sempre deve ser tratado no início de qualquer função, nunca implícito no fluxo principal. O único número par e primo existe e é 2. Ele não tem segredos, mas sua existência única cria efeitos colaterais em qualquer sistema que assume implicitamente que primos são ímpares. Trate-o explicitamente e evite dores de cabeça.