Gerar uma lista de números primos é mais simples do que muitos pensam, mas tem armadilhas práticas
A maioria das pessoas que precisa de uma lista de números primos acaba encontrando geradores online ou scripts prontos. O problema é que a maioria desses geradores não avisa sobre os limites reais de performance, especialmente quando você sai da faixa de milhares e vai para milhões. Eu já precisei de uma lista de primos até 10 milhões para um projeto de criptografia interna, e perder tempo com código que travava ou gastava memória demais é algo que você prefere evitar na segunda vez.
Como funciona o processo na prática
O método mais eficiente para gerar uma lista de números primos é o Crivo de Eratóstenes. Você cria um array de booleanos representando cada número par, começa pelo 2 e marca todos os múltiplos como compostos, depois avança para o próximo número não marcado, repete até a raiz quadrada do limite desejado. O resto dos números marcados como verdadeiros são os primos. Em Python, isso fica algo como:
def crivo_eratostenes(n): Isso roda em segundos para um milhão de números e leva uns poucos minutos para dez milhões, dependendo do hardware.
primos = [True] * (n + 1)
primos[0] = primos[1] = False
for i in range(2, int(n0.5) + 1):
if primos[i]:
for j in range(i*i, n + 1, i):
primos[j] = False
return [i for i, p in enumerate(primos) if p]
O problema que ninguém avisa
Eu descobri na prática que o Crivo de Eratóstenes clássico começa a sofrer bastante quando você precisa de uma lista de números primos acima de 50 milhões. A array de booleanos vira uma montanha de memória. No meu caso, o servidor de staging começou a trocar memória para o disco, o que transformou um cálculo que levaria minutos em algo que ficou horas. A solução foi implementar uma versão otimizada com segmentação: dividir o intervalo em blocos de tamanho gerenciável e processar cada bloco individualmente, mantendo apenas os primos necessários na memória. Um detalhe importante que esquecem: o algoritmo começa marcando múltiplos a partir de i*i. Isso já corta uma quantidade razoável de operações desnecessárias, mas se você não tomar cuidado com o incremento do loop interno, ainda gasta ciclos Processando números que já foram marcados.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Pontos que iniciantes erram
Muita gente implementa o crivo usando divisão direta, testando se cada número é divisível por qualquer outro até sua metade. Isso funciona para listas pequenas, mas escala muito mal. Testar primalidade por tentativa de divisão até n/2 para números na casa dos bilhões simplesmente não cabe em um tempo útil. Outro erro comum é confiar em bibliotecas que prometem gerar listas grandes sem explicar o consumo de memória. A biblioteca SymPy, por exemplo, tem uma função primes() útil, mas ela não foi feita para extrair listas massivas de uma vez só. Ela guarda tudo em memória e pode estourar o limite rapidamente.
Dica para quem precisa de uma lista de números primos para uso direto
Se você não quer implementar nada e só precisa baixar uma lista pronta, existem arquivos de texto com primos até 100 milhões disponíveis publicamente. O sítio factorization.net mantém tabelas bem organizadas. Basta procurar por "prime numbers up to 10 million" ou "prime numbers up to 100 million" que os arquivos CSV aparecem. O download é direto, sem cadastro, e o tamanho do arquivo para 10 milhões é cerca de 170 MB em texto plano, o que é razoável para a maioria dos bancos de dados. Para quem trabalha com segurança, vale lembrar que primos grandes têm utilidade diferente de primos pequenos. Se o objetivo é estudar fatoração ou gerar chaves RSA, começar com uma lista de números primos menores ajuda a entender o padrão, mas a segurança real depende de primos com centenas de dígitos, que não cabem em nenhuma lista pronta.
O Crivo de Eratóstenes com segmentação, quando bem ajustado, gera uma lista de números primos até 100 milhões em torno de 3 a 5 minutos em uma máquina moderna com 8 GB de RAM. Sem segmentação, o tempo sobe para algo em torno de 40 minutos ou mais, e o uso de memória ultrapassa 4 GB. A diferença é significativa se você estiver rodando isso em um ambiente com recursos limitados.
Resumo rápido para colocar a mão na massa
Use Crivo de Eratóstenes para faixas até 10 milhões. Para faixas maiores, considere a versão segmentada. Baixe tabelas prontas se só precisa dos dados e não quer programar. Evite testes de divisibilidade para listas grandes. E fique atento à memória: um vetor de bools para 100 milhões ocupa aproximadamente 100 MB, mas em Python puro o overhead pode chegar a 500 MB ou mais por causa da estrutura de objetos internos.