Como gerar números aleatórios entre 1 e 10 — e por que a maioria das pessoas faz errado
Gerar um número aleatório de 1 a 10 parece trivial. Todo mundo já fez isso pelo menos uma vez em algum tutorial de programação. O problema é que, quando você para para olhar o que acontece por baixo dos panos, existem várias maneiras de fazer isso de forma errada, e a diferença entre certo e errado só aparece quando o código vai parar na produção. O método mais comum em quase todas as linguagens é pegar o resultado de uma função de geração de números pseudoaleatórios e aplicar uma operação de módulo. Em JavaScript, por exemplo, você escreve algo como Math.floor(Math.random() * 10) + 1. A função Math.random() retorna um número decimal entre 0 (inclusivo) e 1 (exclusivo). Ao multiplicar por 10, você amplia o intervalo para 0 até quase 10. O floor arredonda para baixo, resultando em um inteiro de 0 a 9. Somar 1 empurra o intervalo para 1 a 10. Pronto, certo? Quase.
Por que escolhe um número de 1 a 10 não é tão simples quanto parece
O verdadeiro problema aparece quando você entende como os geradores pseudoaleatórios funcionam por dentro. A maioria das linguagens usa o algoritmo Mersenne Twister ou variações do computador de estado linear. Eles produzem sequências que parecem aleatórias, mas são completamente determinísticas. Se você souber o estado inicial, ou seed, consegue prever todos os números que serão gerados. Isso não é teoria. Eu já vi um sistema de distribuição de prêmios em um projeto interno quebrar porque o gerador era instanciado dentro de um loop sem seed adequada, e o seed vinha do relógio do sistema com resolução insuficiente. Em máquinas rápidas, múltiplas iterações tinham o mesmo timestamp, e o mesmo "número aleatório" era retornado repetidamente. O bug levou cerca de três semanas para ser identificado porque os logs pareciam normais à primeira olhada. A lição prática é: nunca confie em seeds automáticas baseadas no tempo para códigos que rodam em loops, containers efêmeros ou ambientes serverless. Se precisar de aleatoriedade com qualidade, use a semente da própria linguagem (como random.seed() com fontes do sistema em Python) ou bibliotecas criptograficamente seguras quando o contexto exigir.
Outro ponto que muitos ignoram é a questão do viés de módulo. Quando você pega um gerador que produz números em um intervalo maior e aplica o operador %, o resultado pode não ter distribuição uniforme perfeita. Por exemplo, se o gerador base produz números de 0 a 99 e você usa % 10, os números 0 a 9 aparecem com frequência ligeiramente diferente dependendo de como o range base se encaixa. Para um intervalo de 1 a 10 isso é praticamente imperceptível em uso comum, mas em simulações estatísticas ou testes A/B com amostras pequenas, o viés pode distorcer resultados. A solução é rejeitar valores fora do range compatível e pedir um novo sorteio, um técnica chamada rejection sampling.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Implementações práticas por linguagem
Em Python, a forma correta e mais simples é usar a biblioteca random: random.randint(1, 10). Ela lida com tudo internamente — seeding, distribuição, limite inclusivo nas duas pontas. Se você precisa de segurança criptográfica, como em tokens ou senhas, use secrets.choice(range(1, 11)) em vez de random, porque a biblioteca random não é adequada para esses cenários. No caso do JavaScript, além do Math.random(), o padrão moderno oferece crypto.getRandomValues(), que é criptograficamente seguro. Um exemplo funcional seria usar um Uint8Array e mapear o valor para o intervalo desejado com rejection sampling embutido.
No PHP, a função mt_rand(1, 10) é preferível a rand() porque usa o algoritmo Mersenne Twister, que tem mais longo e distribuição estatisticamente melhor. A diferença é pequena para uso casual, mas relevante em sistemas que geram milhares de valores por segundo.
Quando não usar números aleatórios simples
Existem cenários onde escolher um número de 1 a 10 de forma ingênua causa problemas reais. Loterias, sistemas de embaralhamento de dados, seed de testes automatizados, e qualquer coisa relacionada a segurança ou conformidade regulatória exige geradores com certificação específica. Nesses casos, recorrer a bibliotecas dedicadas ou a APIs de fonte de entropia do sistema operacional é o mínimo aceitável. Outro problema comum é a confusão entre aleatoriedade e imparcialidade. Um gerador pode ser tecnicamente correto e ainda assim produzir sequências aparentemente previsíveis para um observador humano. Sequências como 1, 1, 1, 1, 2, 2, 2, 3, 3, 4 parecem tendenciosas, mas têm probabilidade idêntica a qualquer outra sequência de dez números no mesmo intervalo. Não existe "padrão certo" em uma amostra tão pequena. Quem reclama desse tipo de coisa geralmente está intuindo padrões que não existem — um viés cognitivo chamado clustering illusion, bem documentado em estudos sobre percepção humana de aleatoriedade.
Se o seu objetivo é apenas selecionar algo aleatoriamente para uso interno, para um sorteio simples, para um teste rápido, a implementação básica da sua linguagem funciona perfeitamente. O importante é saber quando parar de tratar como trivia e começar a levar a questão a sério. A linha é tênue, mas é fácil perceber quando você a cruzou: é quando o custo de um resultado enviesado ou previsível supera o custo de uma solução mais robusta.