Come generare casuale distribuito casualmente da un intervallo intero?

Dato l’inizio e la fine di un intervallo intero, come faccio a calcolare un intero casuale distribuito normalmente tra questo intervallo?

Mi rendo conto che la distribuzione normale va in – + infinito. Immagino che le code possano essere tagliate, quindi quando un random viene calcolato al di fuori dell’intervallo, ricalcalo. Questo eleva la probabilità di numeri interi nell’intervallo, ma finché questo effetto è tollerabile (<5%), va bene.

public class Gaussian { private static bool uselast = true; private static double next_gaussian = 0.0; private static Random random = new Random(); public static double BoxMuller() { if (uselast) { uselast = false; return next_gaussian; } else { double v1, v2, s; do { v1 = 2.0 * random.NextDouble() - 1.0; v2 = 2.0 * random.NextDouble() - 1.0; s = v1 * v1 + v2 * v2; } while (s >= 1.0 || s == 0); s = System.Math.Sqrt((-2.0 * System.Math.Log(s)) / s); next_gaussian = v2 * s; uselast = true; return v1 * s; } } public static double BoxMuller(double mean, double standard_deviation) { return mean + BoxMuller() * standard_deviation; } public static int Next(int min, int max) { return (int)BoxMuller(min + (max - min) / 2.0, 1.0); } } 

Probabilmente ho bisogno di ridimensionare la deviazione standard in modo relativo rispetto all’intervallo, ma non capisco come.

Risposta:

  // Will approximitely give a random gaussian integer between min and max so that min and max are at // 3.5 deviations from the mean (half-way of min and max). public static int Next(int min, int max) { double deviations = 3.5; int r; while ((r = (int)BoxMuller(min + (max - min) / 2.0, (max - min) / 2.0 / deviations)) > max || r < min) { } return r; } 

Se il metodo Box-Muller restituisce una distribuzione normale “standard”, avrà media 0 e deviazione standard 1. Per trasformare una normale distribuzione standard, moltiplichi il tuo numero casuale per X per ottenere la deviazione standard X, e aggiungi Y per ottenere significa Y, se la memoria mi serve correttamente.

Vedere la sezione dell’articolo di Wikipedia sulla normalizzazione delle variabili normali standard (proprietà 1) per una dimostrazione più formale.


In risposta al tuo commento, la regola generale è che il 99,7% di una distribuzione normale sarà entro +/- 3 volte la deviazione standard. Se hai bisogno di una distribuzione normale da 0 a 100, ad esempio, la tua media sarà a metà strada e la tua SD sarà (100/2) / 3 = 16.667. Quindi, indipendentemente dai valori che si ottengono dall’algoritmo Box-Muller, moltiplicare per 16.667 per “estendere” la distribuzione, quindi aggiungere 50 per “centrarlo”.


John, in risposta al tuo ultimo commento, non sono davvero sicuro di quale sia il punto della funzione Next . Utilizza sempre una deviazione standard di 1 e una media di metà tra il minimo e il massimo.

Se si desidera una media di Y, con ~ 99,7% dei numeri nell’intervallo da -X a + X, quindi si chiama BoxMuller(Y, X/3) .

Bene, il sigma -2 * sigma .. + 2 * vi darà il 95% della curva campana. (controlla la sezione “Deviazione standard e intervalli di confidenza” nell’articolo wiki già citato).

Quindi modifica questo pezzo:

 return (int)BoxMuller(min + (max - min) / 2.0, 1.0); 

e modifica 1.0 (deviazione standard) a 2.0 (o anche più se si desidera una copertura superiore al 95%)

 return (int)BoxMuller(min + (max - min) / 2.0, 2.0);