É possível obter um número aleatório entre 1 e 100 e manter os resultados principalmente dentro da faixa de 40 a 60? Quero dizer, raramente sai desse intervalo, mas quero que ele esteja principalmente dentro desse intervalo ... É possível com JavaScript / jQuery?
Agora eu estou apenas usando o básico Math.random() * 100 + 1
.
javascript
algorithm
random
numbers
Darryl Huffman
fonte
fonte
Respostas:
A maneira mais simples seria gerar dois números aleatórios de 0 a 50 e adicioná-los.
Isso fornece uma distribuição tendenciosa para 50, da mesma maneira que rola dois vieses de dados para 7.
De fato, usando um número maior de "dados" (como sugere @Falco) , é possível aproximar mais uma curva de sino:
JSFiddle: http://jsfiddle.net/797qhcza/1/
fonte
Você tem boas respostas aqui que fornecem soluções específicas; deixe-me descrever para você a solução geral. O problema é:
A solução geral para esse problema é calcular a função quantil da sua distribuição desejada e aplicar a função quantil à saída da sua fonte uniforme.
A função quantil é o inverso da integral da sua função de distribuição desejada . A função de distribuição é a função em que a área sob uma parte da curva é igual à probabilidade de o item escolhido aleatoriamente estar nessa porção.
Eu dou um exemplo de como fazer isso aqui:
http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/
O código está em C #, mas os princípios se aplicam a qualquer idioma; deve ser fácil adaptar a solução ao JavaScript.
fonte
Tirar matrizes de números etc. não é eficiente. Você deve fazer um mapeamento que leva um número aleatório entre 0 a 100 e mapeia a distribuição necessária. Portanto, no seu caso, você pode levar para obter uma distribuição com mais valores no meio do seu intervalo.
f(x)=-(1/25)x2+4x
fonte
x
entre 0 e 100 (retirada desta pergunta ):y = (Math.sin(2 * Math.PI * (x/100 - 1/4)) + 1) / 2
Eu poderia fazer algo como configurar uma "chance" para o número ser permitido "fora dos limites". Neste exemplo, 20% de chance de o número ser 1-100, caso contrário, 40-60:
violino: http://jsfiddle.net/kbv39s9w/
fonte
Eu precisava resolver esse problema há alguns anos e minha solução foi mais fácil do que qualquer outra resposta.
Eu gerei 3 randoms entre os limites e calculei a média deles. Isso puxa o resultado em direção ao centro, mas deixa completamente possível alcançar as extremidades.
fonte
BellFactor
de 3.Ele parece estúpido, mas você pode usar rand duas vezes:
fonte
Claro que é possível. Faça um 1-100 aleatório. Se o número for <30, gere um número no intervalo de 1 a 100, se não gerar no intervalo de 40 a 60.
fonte
Existem várias maneiras diferentes de gerar esses números aleatórios. Uma maneira de fazer isso é calcular a soma de vários números uniformemente aleatórios. Quantos números aleatórios você soma e qual é o intervalo deles determinará a aparência da distribuição final.
Quanto mais números você resumir, mais será inclinado para o centro. O uso da soma de 1 número aleatório já foi proposto em sua pergunta, mas, como você percebe, não é direcionado para o centro do intervalo. Outras respostas propõem o uso da soma de 2 números aleatórios ou da soma de 3 números aleatórios .
Você pode obter ainda mais preconceitos em direção ao centro do intervalo, somando mais números aleatórios. No extremo, você pode pegar a soma de 99 números aleatórios, cada um com 0 ou 1. Isso seria uma distribuição binomial. (As distribuições binomiais podem, em certo sentido, ser vistas como a versão discreta das distribuições normais). Isso ainda pode, em teoria, abranger toda a gama, mas tem tanto viés em direção ao centro que você nunca deve esperar vê-lo atingir os pontos finais.
Essa abordagem significa que você pode ajustar o quanto você deseja.
fonte
Que tal usar algo como isto:
A maneira como eu codifiquei permite definir algumas variáveis:
loops = número de resultados
tentativas = número de vezes que a função tentará obter um número entre 40-60 antes que pare de executar o loop while
Bônus adicionado: Usa do while! Awesomeness no seu melhor
fonte
Você pode escrever uma função que mapeie valores aleatórios entre
[0, 1)
de[1, 100]
acordo com o peso. Considere este exemplo:Aqui, o valor é
0.95
mapeado para o valor entre[61, 100]
.De fato, temos
.05 / .1 = 0.5
, que, quando mapeados[61, 100]
, produz81
.Aqui está a função:
fonte
Aqui está uma solução ponderada em 3/4 40-60 e 1/4 fora desse intervalo.
fonte
Ok, então decidi adicionar outra resposta, porque senti que minha última resposta, assim como a maioria das respostas aqui, usa algum tipo de meio meio estatístico de obter um retorno do resultado do tipo curva em sino. O código que forneço abaixo funciona da mesma maneira que quando você lança um dado. Portanto, é mais difícil obter 1 ou 99, mas mais fácil obter 50.
fonte
Eu recomendo usar a distribuição beta para gerar um número entre 0-1 e depois escalá-lo. É bastante flexível e pode criar muitas formas diferentes de distribuição.
Aqui está um amostrador rápido e sujo:
fonte
fonte
A melhor solução para esse mesmo problema é a proposta por BlueRaja - Danny Pflughoeft, mas acho que também vale a pena mencionar uma solução mais rápida e mais geral.
Quando eu tenho que gerar números aleatórios (strings, pares de coordenadas, etc.) atendendo aos dois requisitos de
Geralmente começo criando uma matriz de números (strings, pares de coordenadas etc.) cumprindo o requisito (no seu caso: uma matriz de números que contém os mais prováveis várias vezes). Em seguida, escolha um item aleatório dessa matriz. Dessa forma, você só precisa chamar a função aleatória cara uma vez por item.
fonte
Distribuição
Solução
Solução genérica
fonte
Você pode usar um número aleatório auxiliar para gerar números aleatórios em 40-60 ou 1-100:
fonte
Se você pode usar a
gaussian
função, use-a. Esta função retorna o número normal comaverage 0
esigma 1
.95% desse número estão dentro
average +/- 2*sigma
. Vocêaverage = 50
esigma = 5
assimfonte
A melhor maneira de fazer isso é gerar um número aleatório que é distribuído igualmente em um determinado conjunto de números e, em seguida, aplicar uma função de projeção ao conjunto entre 0 e 100, onde é mais provável que a projeção atinja os números desejados.
Normalmente, a maneira matemática de conseguir isso é traçar uma função de probabilidade dos números que você deseja. Poderíamos usar a curva de sino, mas, para facilitar o cálculo, basta trabalhar com uma parábola invertida.
Vamos fazer uma parábola de modo que suas raízes estejam em 0 e 100 sem distorcer. Obtemos a seguinte equação:
Agora, toda a área sob a curva entre 0 e 100 é representativa do nosso primeiro conjunto, onde queremos que os números sejam gerados. Lá, a geração é completamente aleatória. Então, tudo o que precisamos fazer é encontrar os limites do nosso primeiro set.
O limite inferior é, obviamente, 0. O limite superior é a integral da nossa função em 100, que é
Portanto, sabemos que precisamos gerar um número entre 0 e 166.666. Então, simplesmente precisamos pegar esse número e projetá-lo em nosso segundo conjunto, que está entre 0 e 100.
Sabemos que o número aleatório que geramos é parte integrante de nossa parábola com uma entrada x entre 0 e 100. Isso significa que simplesmente temos que assumir que o número aleatório é o resultado de F (x) e resolver x.
Nesse caso, F (x) é uma equação cúbica e na forma
F(x) = ax^3 + bx^2 + cx + d = 0
, as seguintes instruções são verdadeiras:Resolver isso para x fornece o número aleatório real que você está procurando, que é garantido no intervalo [0, 100] e tem uma probabilidade muito maior de estar próximo ao centro do que as bordas.
fonte
Esta resposta é realmente boa . Mas eu gostaria de postar instruções de implementação (não gosto de JavaScript, espero que você entenda) para situações diferentes.
Suponha que você tenha intervalos e pesos para cada intervalo:
Informações estáticas iniciais, podem ser armazenadas em cache:
Boundary[n] = Boundary[n - 1] + weigh[n - 1]
eBoundary[0] = 0
. Amostra temBoundary = {0, 1, 3, 103, 108}
Geração de número:
N
do intervalo [0, Soma de todos os pesos).for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
i
intervalo e gere um número aleatório nesse intervalo.Nota adicional para otimizações de desempenho. As faixas não precisam ser ordenadas nem em ordem crescente nem decrescente; portanto, para obter um intervalo mais rápido de consulta de alcance com maior peso, deve-se primeiro e um com menor peso deve durar.
fonte