“Aleatório” é fácil de pedir e surpreendentemente fácil de errar. A diferença entre um gerador em que você pode confiar para um sorteio e um que favorece discretamente certos números se resume a algumas ideias: de onde vem a aleatoriedade, como ela é mapeada em seu range e se você precisa que o sorteio seja imprevisível ou reproduzível. Este gerador é construído em torno dessas distinções – criptograficamente seguro por padrão, imparcial por construção, com um modo propagado opcional para quando a repetibilidade é mais importante do que o sigilo. As seções abaixo explicam o que está acontecendo nos bastidores e como escolher as configurações corretas.
Verdadeiro aleatório vs. pseudo-aleatório
Existem duas famílias de aleatoriedade. Um gerador de números aleatórios verdadeiro (ou hardware) extrai a imprevisibilidade de um processo físico – ruído elétrico, instabilidade de temporização, decaimento radioativo. Um gerador pseudo-aleatório (PRNG) executa uma fórmula determinística a partir de uma semente; sua saída parece aleatória e passa em testes estatísticos, mas toda a sequência é corrigida quando você conhece a semente.
Seu navegador faz a ponte entre os dois. crypto.getRandomValues — a fonte que esta ferramenta usa por padrão — é um PRNG criptograficamente seguro que é continuamente propagado novamente a partir do pool de entropia de hardware do sistema operacional. Para fins práticos, seu resultado é imprevisível e imparcial, por isso é a ferramenta certa para sorteios, tokens de segurança e qualquer coisa em que alguém possa se beneficiar ao adivinhar o próximo valor. O antigo Math.random é um PRNG simples, sem garantias de segurança e não é deliberadamente usado aqui.
Viés de módulo e por que a amostragem de rejeição o corrige
Este é o erro que a maioria dos códigos aleatórios caseiros comete. Para transformar um grande número aleatório em, digamos, um número de 1 a 6, o movimento óbvio é o resto: 1 + (x mod 6). O problema é que a fonte tem 2³² valores possíveis e 2³² não é divisível por 6. Os valores restantes no topo do intervalo se contorcem e caem nos primeiros resultados, tornando 1, 2, 3 e 4 um pouco mais provável do que 5 e 6. Com um dado de seis lados, a inclinação é pequena; com um intervalo grande, ou mais de milhões de sorteios, ele se torna mensurável — e em contextos de segurança é uma verdadeira fraqueza.
A solução é a amostragem de rejeição: calcule o maior múltiplo do seu intervalo que caiba em 2³², extraia valores brutos e jogue fora qualquer um que cair no balde restante antes de pegar o restante. Alguns draws são descartados, mas cada número inteiro no seu range acaba sendo exatamente igualmente provável. Este gerador faz isso para cada número inteiro que produz, então “1–6” é realmente um dado justo e “1–10.000” é realmente uniforme.
Escolhas de loteria únicas versus repetidas e justas
Sorteios “Permitir repetições” com substituição: cada escolha é independente, portanto o mesmo número pode aparecer mais de uma vez — o modelo certo para lançamento de dados e moeda. Sorteios “únicos” sem reposição: cada valor aparece no máximo uma vez, que é o que você deseja para um sorteio, um selecionador de equipe ou uma linha de loteria. Quando você solicita valores únicos, o gerador embaralha o conjunto elegível com um embaralhamento parcial de Fisher-Yates e pega o primeiro k, o que mantém todas as combinações igualmente prováveis e garante que não haja duplicatas.
Dois guarda-corpos são importantes aqui. Você não pode desenhar mais valores exclusivos do que o intervalo contém – pedir 10 números exclusivos de 1 a 6 é impossível, então a ferramenta desenha tudo o que pode e avisa você. E a lista de exclusão remove valores específicos (um vencedor já sorteado, um 13 azarado) do pool antes do sorteio, o que também reduz o pool único.
Quando usar uma semente (reprodutibilidade)
Na maioria das vezes você deseja aleatoriedade e não pode prever, então o modo cripto-seguro padrão está correto. Mas às vezes você quer o o oposto: um empate que você pode repetir quando necessário. É para isso que serve a semente. No modo Seeded, os números vêm do mulberry32, um PRNG determinístico, e a mesma semente com as mesmas configurações sempre produz os mesmos números.
Isso é genuinamente útil. Um pesquisador pode publicar a semente junto com um estudo para que a amostra aleatória seja reproduzível. O anfitrião do sorteio pode anunciar a semente com antecedência para que os participantes possam verificar o sorteio posteriormente, em vez de confiar nele. Um desenvolvedor pode propagar dados de teste para que os testes com falha sejam repetíveis. A desvantagem é que uma sequência propagada é, por design, previsível para qualquer pessoa que conheça a semente. Portanto, nunca use o modo propagado para gerar senhas, chaves ou qualquer coisa que deva permanecer secreta.
É justo? Lendo a distribuição
“Isso é realmente aleatório?” é uma pergunta justa, e a guia Estatísticas existe para respondê-la. Para um único sorteio pequeno, você não pode dizer muito – cinco números de 1 a 100 não parecerão espaçados uniformemente, e isso é normal; a verdadeira aleatoriedade é irregular, não organizada. O padrão só emerge em escala. Jogue um dado algumas centenas de vezes ou gere uma amostra grande e as barras de frequência se achatam em alturas iguais, o que é a assinatura visual de uma distribuição uniforme.
Este também é o antídoto para a falácia do jogador. Uma sequência de cinco caras não resulta em coroa “devida” – cada lançamento é independente e permanece 50/50, e a contagem contínua simplesmente oscila em direção a 50% à medida que o número de lançamentos aumenta (a lei dos grandes números), sem que nenhum lançamento individual seja influenciado pelos anteriores.