Generare numeri interi casuali in JavaScript in un intervallo specifico?

Come posso generare numeri interi casuali tra due variabili specificate in JavaScript, ad esempio x = 4 e y = 8 produrrebbero qualsiasi 4, 5, 6, 7, 8?

Soluzione

Ci sono alcuni esempi nella pagina 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;
}

hr>

Ecco la logica che c'è dietro. È una semplice regola del tre:

Math.random() restituisce un Numero tra 0 (incluso) e 1 (esclusivo). Quindi abbiamo un intervallo come questo:

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

Ora, vorremmo un numero tra min (incluso) e max (esclusivo):

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

Possiamo usare il Math.random per ottenere il corrispondente nell'intervallo [min, max]. Ma, prima dobbiamo fattorizzare un po' il problema sottraendo min dal secondo intervallo:

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

Questo dà:

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

Possiamo ora applicare Math.random e calcolare il corrispondente. Scegliamo un numero casuale:

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

Quindi, per trovare x, dovremmo fare:

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

Non dimenticare di aggiungere min, in modo da ottenere un numero nell'intervallo [min, max]:

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

Questa era la prima funzione della MDN. La seconda, restituisce un numero intero tra min e max, entrambi inclusi.

Ora, per ottenere numeri interi, potresti usare round, ceil o floor.

Potresti usare Math.round(Math.random() * (max - min)) + min, questo però dà una distribuzione non uniforme. Entrambi, min e max hanno solo circa la metà delle possibilità di tirare:

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

Con max escluso dall'intervallo, ha ancora meno possibilità di tirare rispetto a min.

Con Math.floor(Math.random() * (max - min +1)) + min si ha una distribuzione perfettamente uniforme.

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

Non puoi usare ceil() e -1 in questa equazione perché max ha ora una possibilità in meno di tirare, ma puoi tirare anche il risultato (indesiderato) min-1.

Commentari (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
Commentari (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)));
}

Per testare questa funzione, e variazioni di questa funzione, salvate il seguente HTML/JavaScript in un file e apritelo con un browser. Il codice produrrà un grafico che mostra la distribuzione di un milione di chiamate di funzione. Il codice registrerà anche i casi limite, quindi se la funzione produce un valore maggiore del massimo, o minore del minimo, voi lo saprete.




        <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 
Commentari (0)