Ferramenta de Seleção Aleatória
Ferramenta de seleção aleatória justa para sorteios, escolhas e extrações
O que é uma Ferramenta de Seleção Aleatória?
Um seletor aleatório escolhe um item de uma lista sem que uma pessoa decida manualmente. Ele é útil para participação em sala, ordem de fala em reuniões, sorteios simples, distribuição de tarefas, escolha de almoço, dinâmicas de equipe e qualquer situação em que uma escolha neutra visível ajuda a evitar viés. Esta página trabalha com uma lista linha por linha, pode animar o sorteio, manter histórico local e evitar repetições removendo itens já escolhidos do conjunto restante. A aleatoriedade pode tornar a escolha justa em sentido estatístico, mas não valida identidades, não remove automaticamente nomes duplicados e não fornece prova auditável. Para sorteios oficiais, elegibilidade ou entrega de prêmios, use um processo com registros e regras.
Como Usar
Etapas da Operação
- Insira as opções na caixa de texto, uma por linha
- Defina o número de itens a selecionar
- Escolha se deseja permitir duplicatas
- Clique no botão 'Iniciar Sorteio'
- Veja os resultados no lado direito
Dicas de Sorteio Justo
- Coloque um candidato por linha e remova espaços ou duplicatas acidentais, a menos que as duplicatas sejam intencionalmente permitidas.
- Para sorteios públicos, defina a semente, regra de duplicatas e regra de resorteio antes de começar, para que o resultado seja mais fácil de explicar.
Casos de uso
Princípio técnico
O seletor aleatório é construído sobre a Web Crypto API (W3C, WHATWG), especificamente crypto.getRandomValues(typedArray), que é a única fonte de aleatoriedade criptograficamente segura exposta nos navegadores. Internamente, o navegador chama o CSPRNG do sistema operacional: CryptGenRandom no Windows (AES-256 em modo CTR-DRBG desde o Windows 10), getrandom(2) no Linux (que lê do mesmo pool baseado em ChaCha20 que alimenta o /dev/urandom do kernel), SecRandomCopyBytes no macOS e o equivalente no iOS, Android e BSD. A saída é adequada para geração de chaves, nonces, salts, IVs e qualquer lugar onde a previsibilidade seria um problema de segurança. A distinção 'nível criptográfico' é importante. Math.random() no V8 usa xorshift128+ (um algoritmo rápido e de baixa entropia) e retorna um float de 64 bits em [0, 1); um ator malicioso que observa algumas saídas pode em princípio reconstruir o estado de 128 bits e prever todos os valores futuros. O mesmo vale para SpiderMonkey e JavaScriptCore. Isso torna o Math.random() inadequado para qualquer uso onde o resultado deve ser imprevisível — seleção justa de um vencedor, um token, uma senha de uso único, uma mão de cartas, uma amostra de auditoria. crypto.getRandomValues(typedArray) é a única opção para esses casos. Mapear inteiros uniformes de 32 bits em um índice uniforme em [0, N) sem viés de módulo é o segundo detalhe de engenharia que separa o correto do incorreto. De forma ingênua, idx = randomUint32 % N está errado: se N não divide 2³², os primeiros 2³² mod N valores são ligeiramente mais prováveis. O algoritmo correto é amostragem por rejeição: calcular limit = 2³² - (2³² mod N); sortear um valor de 32 bits r; se r >= limit, sortear novamente; caso contrário retornar r % N. O viés cai de O(N / 2³²) para zero. Para N = 2 ou N potência de 2 o módulo é exato, mas a amostragem por rejeição é o padrão seguro e custa no máximo um novo sorteio em média (e sempre termina). O seletor armazena resultados no localStorage com uma chave versionada, para que uma sessão sobreviva a uma atualização de página e o usuário possa revisar o histórico de sorteios. O histórico não é criptografado ou assinado — é local, não sensível e fácil de limpar. Para o modo sem repetição, o algoritmo sorteia sem reposição usando um embaralhamento parcial Fisher-Yates: na etapa k de N, troca o elemento k com um elemento escolhido uniformemente em [k, N) e trava o elemento k como sorteado. Isso é O(N) de tempo, O(1) de espaço extra, e dá a cada permutação probabilidade igual, que é a garantia combinatória correta. (O ingênuo 'sortear N vezes, rejeitando repetições' também é correto mas O(N²) e pode travar em sessões longas.) Para escolhas ponderadas (cada opção tem sua própria probabilidade), o algoritmo padrão é amostragem por CDF inverso com array de soma de prefixo: construir uma soma de prefixo dos pesos, sortear um real uniforme em [0, total) e fazer busca binária para o menor i tal que prefix[i] >= u. Isso é O(log N) por sorteio, e a soma de prefixo é construída uma vez por alteração. O método alias (Walker-Vose) oferece O(1) por sorteio ao custo de O(N) de configuração, o que vale a pena apenas quando N é grande e a distribuição é fixa.
- Fonte de aleatoriedade: crypto.getRandomValues(typedArray) — a única RNG criptograficamente segura nos navegadores, respaldada pelo CSPRNG do sistema operacional (AES-256 CTR-DRBG no Windows 10+, ChaCha20 no Linux/macOS/iOS/Android).
- Math.random() é xorshift128+ no V8 (e variantes em outros motores): rápido mas previsível. Nunca use para seleção justa, tokens, OTPs ou amostras de auditoria — apenas para ruído visual, animações ou amostragem não segura.
- Mapeamento de índice sem viés: amostragem por rejeição, não módulo. Calcular limit = 2³² - (2³² mod N); se o uint32 aleatório >= limit, sortear novamente; senão retornar r % N. Evita o clássico 'viés de módulo' onde índices de faixa curta aparecem com mais frequência.
- Sorteios sem repetição usam embaralhamento parcial Fisher-Yates em O(N) de tempo, O(1) de espaço: na etapa k troca o elemento k com um elemento uniforme em [k, N), depois trava k. Toda permutação é igualmente provável.
- Escolhas ponderadas usam amostragem por CDF inverso: construir uma soma de prefixo dos pesos uma vez, sortear um real uniforme em [0, total), fazer busca binária para o menor prefix[i] >= u. O(log N) por sorteio.
- O histórico de sorteios é persistido no localStorage com uma chave versionada, então uma sessão sobrevive a uma atualização de página. O histórico é apenas local e não é sensível em termos de segurança — limpe-o pela interface quando terminar.
- Fisher-Yates vs 'sortear N vezes com rejeição': ambos são corretos em distribuição, mas Fisher-Yates é O(N) no total e O(1) de memória, enquanto a rejeição ingênua é O(N²) no pior caso (muitas repetições perto do final de uma lista longa).
- Intervalo de saída e tipos: getRandomValues aceita Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, BigUint64Array — e a página sempre usa Uint32Array para alimentar a etapa de mapeamento de índice.
Exemplos
Sorteio sem repetição a partir de uma lista de candidatos
Lista de entrada (um por linha):
Alice
Bob
Charlie
David
Eve
Frank
Permitir duplicatas: OFF Sorteios: 3
Resultado:
#1: Charlie
#2: Alice
#3: Frank
(Bob, David, Eve permanecem na lista)
A página chama crypto.getRandomValues() em um Uint32Array para gerar
um inteiro uniforme em [0, n) a cada sorteio, onde n é o número de
candidatos restantes. Cada nome tem a mesma probabilidade 1/n em cada
sorteio, e o índice escolhido é fixado antes do início da animação.Sorteio com repetição e histórico com timestamp
Lista de entrada (um por linha):
Cara
Coroa
Permitir duplicatas: ON Sorteios: 5
Resultado:
#1 (14:23:01): Cara
#2 (14:23:01): Coroa
#3 (14:23:01): Cara
#4 (14:23:01): Cara
#5 (14:23:01): Coroa
No modo com repetição, a mesma entrada pode ser sorteada em rodadas
consecutivas e a lista nunca diminui. O timestamp do sorteio é
adicionado a cada registro, então a mesma lista de candidatos pode ser
reutilizada entre rodadas enquanto o histórico mostra exatamente quando
cada sorteio ocorreu. Limpe os registros separadamente da lista de
candidatos - eles ficam armazenados em chaves diferentes do localStorage.Trecho em JavaScript da seleção subjacente
// Escolhe um índice em [0, n) usando Web Crypto (CSPRNG)
function pickIndex(n) {
// crypto.getRandomValues fornece um valor uniforme de 32 bits; o módulo n
// é seguro aqui porque n é no máximo alguns milhares para uma lista de sorteio,
// e o viés de módulo é desprezível (2^32 / n é grande).
const buf = new Uint32Array(1);
crypto.getRandomValues(buf);
return buf[0] % n;
}
// pickIndex(6) -> ex. 4 (Charlie no exemplo acima)
// pickIndex(2) -> 0 ou 1 (Cara ou Coroa)
//
// Obs.: para listas enormes onde n se aproxima de 2^32, use rejection sampling
// para remover o viés de módulo, por exemplo:
// const limit = Math.floor(0xFFFFFFFF / n) * n;
// let r; do { crypto.getRandomValues(buf); r = buf[0]; } while (r >= limit);Verificação de imparcialidade em 1.000 sorteios
Lista: ['A', 'B', 'C', 'D'] (4 entradas, proporção esperada 25,0%)
Sorteios: 1.000 Permitir duplicatas: ON
Observado:
A: 247 (24,7%)
B: 256 (25,6%)
C: 248 (24,8%)
D: 249 (24,9%)
Uma execução de 1.000 sorteios com crypto.getRandomValues deve ficar dentro
de cerca de +/- 3 pontos percentuais da proporção esperada para cada entrada;
desvios maiores (por exemplo, uma entrada em 35%) geralmente indicam que a
implementação está chamando Math.random() ou aplicando o módulo de forma errada.
Para um sorteio regulamentado, salve a lista de origem, a fonte do seed aleatório
(entropia do navegador/SO), o timestamp do sorteio e uma assinatura de testemunha
- o localStorage não é um sistema de registro durável.Perguntas frequentes
O sorteio é realmente aleatório?
Sim. A seleção usa crypto.getRandomValues da Web Crypto API, que é criptograficamente forte. Cada opção tem probabilidade igual, a menos que você configure pesos.
A mesma opção pode ser sorteada duas vezes seguidas?
Sim — é assim que funciona a seleção aleatória independente. Com 5 opções, a probabilidade de duas escolhas iguais consecutivas é 1/5 = 20%. Se você não quer repetições, ative 'remover após seleção', que sorteia sem reposição até a lista ficar vazia.
Como funciona o 'sortear N itens'?
Por padrão, a amostragem é sem reposição — cada item pode ser selecionado no máximo uma vez por sorteio de N itens. Ative 'com reposição' se duplicatas forem aceitáveis (por exemplo, sortear N tarefas para uma única pessoa). N não pode ser maior que o tamanho da lista no modo sem reposição.
Posso adicionar pesos para influenciar o sorteio?
Algumas versões suportam pesos por opção (por exemplo, opção A com peso 3, opção B com peso 1 — A tem 3x mais chances). A página normaliza os pesos em probabilidades. Sem pesos, todas as opções têm a mesma probabilidade.
Por que isso é mais justo do que escolher 'no feeling'?
Humanos são ruins em ser aleatórios — tendemos a evitar escolhas recentes, escolher demais opções marcantes e ter viés inconsciente em favor de nomes que reconhecemos. Uma escolha por computador remove esse viés, o que faz sorteios parecerem mais limpos para os participantes.
Minha lista é salva?
Algumas versões salvam no localStorage para que a lista persista no mesmo navegador. Fechar a aba ou trocar de navegador faz com que ela se perca, a menos que você tenha exportado. Nada é enviado para a internet.
Devo usá-lo para sorteios oficiais ou loterias legais?
Não. Rifas, loterias e sorteios de apostas legais exigem procedimentos aleatórios auditáveis, geralmente com hardware físico ou RNG certificado. Uma ferramenta web genérica não é documentada nem auditada — use apenas para sorteios de escritório e brincadeiras informais.