Gerar números inteiros aleatórios em JavaScript em um intervalo específico?

Como posso gerar números inteiros aleatórios entre duas variáveis especificadas em JavaScript, por exemplo x = 4 e y = 8, que sairiam qualquer um de 4, 5, 6, 7, 8?

Solução

Há alguns exemplos na página Mozilla Developer Network:

/**
 * Returns a random number between min (inclusive) and max (exclusive)
 */
function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}

/**
 * Returns a random integer between min (inclusive) and max (inclusive).
 * The value is no lower than min (or the next integer greater than min
 * if min isn't an integer) and no greater than max (or the next integer
 * lower than max if max isn't an integer).
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

Aqui está a lógica por trás disso. É uma regra simples de três:

Math.random() retorna um Número entre 0 (inclusive) e 1 (exclusivo). Então nós temos um intervalo como este:

[0 .................................... 1)

Agora, gostaríamos de um número entre min (inclusive) e max (exclusivo):

[0 .................................... 1)
[min .................................. max)

Podemos utilizar o Math.random para obter o correspondente no intervalo [min, max). Mas, primeiro devemos considerar um pouco o problema subtraindo o min do segundo intervalo:

[0 .................................... 1)
[min - min ............................ max - min)

Isto dá:

[0 .................................... 1)
[0 .................................... max - min)

Podemos agora aplicar Math.random e depois calcular o correspondente. Vamos escolher um número aleatório:

                Math.random()
                    |
[0 .................................... 1)
[0 .................................... max - min)
                    |
                    x (what we need)

Então, para encontrar o x, nós faríamos:

x = Math.random() * (max - min);

Não se esqueça de adicionar min de volta, para que tenhamos um número no intervalo [min, max]:

x = Math.random() * (max - min) + min;

Essa foi a primeira função da MDN. A segunda, retorna um número inteiro entre min e max, ambas inclusivas.

Agora para obter números inteiros, você poderia usar "redondo", "tecto" ou "chão".

Você poderia utilizar Math.round(Math.random() * (max - min)) + min, isto no entanto dá uma distribuição não uniforme. Ambos, min e max só têm aproximadamente metade da chance de rolar:

min...min+0.5...min+1...min+1.5   ...    max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘   ← Math.round()
   min          min+1                          max

Com o max excluído do intervalo, tem ainda menos chance de rolar do que o min.

Com Math.floor(Math.random() * (max - min +1)) + min você tem uma distribuição perfeitamente uniforme.

min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
|        |        |         |        |        |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘   ← Math.floor()
   min     min+1               max-1    max

Você não pode utilizar ceil() e -1 nessa equação porque max agora tinha um pouco menos de chance de rolar, mas você pode rolar o resultado (indesejado) min-1 também.

Comentários (29)
function getRandomizer(bottom, top) {
    return function() {
        return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
    }
}

uso:


var rollDie = getRandomizer( 1, 6 );

var results = ""
for ( var i = 0; i
Comentários (7)
function getRandomInt(lower, upper)
{
    //to create an even sample distribution
    return Math.floor(lower + (Math.random() * (upper - lower + 1)));

    //to produce an uneven sample distribution
    //return Math.round(lower + (Math.random() * (upper - lower)));

    //to exclude the max value from the possible values
    //return Math.floor(lower + (Math.random() * (upper - lower)));
}

Para testar esta função, e variações desta função, salve o HTML/JavaScript abaixo em um arquivo e abra com um navegador. O código produzirá um gráfico mostrando a distribuição de um milhão de chamadas de função. O código também registrará os casos de borda, então se a função produzir um valor maior que o máximo, ou menor que o mínimo, você.saberá.sobre.ele.




        <script type="text/javascript">
        function getRandomInt(lower, upper)
        {
            //to create an even sample distribution
            return Math.floor(lower + (Math.random() * (upper - lower + 1)));

            //to produce an uneven sample distribution
            //return Math.round(lower + (Math.random() * (upper - lower)));

            //to exclude the max value from the possible values
            //return Math.floor(lower + (Math.random() * (upper - lower)));
        }

        var min = -5;
        var max = 5;

        var array = new Array();

        for(var i = 0; i 
Comentários (0)