2009-06-30 5 views
99

È possibile generare un numero casuale tra 2 doppi?Numero casuale tra 2 numeri doppi

Esempio:

public double GetRandomeNumber(double minimum, double maximum) 
{ 
    return Random.NextDouble(minimum, maximum) 
} 

Poi mi chiamano con il seguente:

double result = GetRandomNumber(1.23, 5.34); 

Ogni pensiero sarebbe apprezzato.

risposta

241

Sì.

Random.NextDouble restituisce un doppio compreso tra 0 e 1. Quindi lo si moltiplica in base all'intervallo da raggiungere (differenza tra massimo e minimo) e quindi aggiunto alla base (minimo).

public double GetRandomNumber(double minimum, double maximum) 
{ 
    Random random = new Random(); 
    return random.NextDouble() * (maximum - minimum) + minimum; 
} 

Il codice reale dovrebbe essere casuale un membro statico. Ciò consentirà di risparmiare il costo della creazione del generatore di numeri casuali e ti consentirà di chiamare GetRandomNumber molto frequentemente. Dal momento che stiamo inizializzando un nuovo RNG con ogni chiamata, se chiami abbastanza velocemente che l'ora del sistema non cambia tra le chiamate, l'RNG verrà seminato con lo stesso timestamp e genererà lo stesso flusso di numeri casuali.

+24

Basta guardare fuori se si chiama GetRandomNumber() in un ciclo in quanto genererà lo stesso valore più e più volte –

+0

@ John - Buon punto, ho aggiunto questo alla mia risposta. – Michael

+0

perfetto! questo è quello che stavo cercando. Grazie mille – CodeLikeBeaker

6

L'approccio più semplice genererebbe semplicemente un numero casuale compreso tra 0 e la differenza dei due numeri. Quindi aggiungi il più piccolo dei due numeri al risultato.

3

Si potrebbe utilizzare il codice in questo modo:

public double getRandomNumber(double minimum, double maximum) { 
    return minimum + randomizer.nextDouble() * (maximum - minimum); 
} 
+2

Whow, è apparso un magico 'randomizer var' !! – Lucas

2

Si potrebbe fare questo:

public class RandomNumbers : Random 
{ 
    public RandomNumbers(int seed) : base(seed) { } 

    public double NextDouble(double minimum, double maximum) 
    { 
     return base.NextDouble() * (maximum - minimum) + minimum; 
    } 
} 
0

A proposito di generare lo stesso numero casuale se lo si chiama in un ciclo di una soluzione elegante è quello di dichiarare la nuovo oggetto Random() al di fuori del ciclo come variabile globale.

Si noti che è necessario dichiarare l'istanza della classe Random al di fuori della funzione GetRandomInt se si sta per eseguirlo in un ciclo.

"Perché è questo?" Chiedi.

Bene, la classe Random genera effettivamente numeri pseudo casuali, con il "seme" per il randomizzatore che rappresenta l'ora del sistema. Se il tuo loop è sufficientemente veloce, il tempo di clock del sistema non apparirà diverso dal randomizzatore e ogni nuova istanza della classe Random inizierà con lo stesso seme e ti darà lo stesso numero pseudo casuale.

Source è qui: http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/

+0

Questo è più adatto come commento, poiché non tenta nemmeno di rispondere alla domanda effettiva di OP. –

28

Johnny5 ha suggerito la creazione di un metodo di estensione. Ecco un esempio di codice più completo che mostra come si possa fare ciò:

public static class RandomExtensions 
{ 
    public static double NextDouble(
     this Random random, 
     double minValue, 
     double maxValue) 
    { 
     return random.NextDouble() * (maxValue - minValue) + minValue; 
    } 
} 

Ora si può chiamare come se si trattasse di un metodo nella classe Random:

Random random = new Random(); 
double value = random.NextDouble(1.23, 5.34); 

Nota che non si deve creare un sacco di nuovi oggetti Random in un ciclo perché questo renderà probabile che si ottenga lo stesso valore molte volte di seguito. Se hai bisogno di molti numeri casuali, crea un'istanza di Random e riutilizzala.

1

Cosa succede se uno dei valori è negativo? Non sarebbe un'idea migliore essere:

double NextDouble(double min, double max) 
{ 
     if (min >= max) 
      throw new ArgumentOutOfRangeException();  
     return random.NextDouble() * (Math.Abs(max-min)) + min; 
} 
+0

Grazie per le idee aggiuntive. Molto utile per una vecchia domanda :) – CodeLikeBeaker

+5

Penso che 'Math.Abs ​​()' sia ridondante. Dato che hai assicurato che 'min> = max', quindi' max - min' deve essere comunque un numero non negativo. –

0
Random random = new Random(); 

double NextDouble(double minimum, double maximum) 
{ 

    return random.NextDouble()*random.Next(minimum,maximum); 

} 
4

attenzione: se si sta generando il random all'interno di un ciclo, come per esempio for(int i = 0; i < 10; i++), non mettere la dichiarazione new Random() all'interno del ciclo.

Da MSDN:

I generazione di numeri casuali inizia da un valore di inizializzazione. Se lo stesso seme viene utilizzato ripetutamente, viene generata la stessa serie di numeri. Un modo per produrre sequenze diverse consiste nel rendere il valore seme dipendente dal tempo, producendo così una serie diversa con ogni nuova istanza di Random di . Per impostazione predefinita, il costruttore senza parametri della classe Random utilizza l'orologio di sistema per generare il valore del seme ...

Quindi, sulla base di questo fatto, fare qualcosa come:

var random = new Random(); 

for(int d = 0; d < 7; d++) 
{ 
    // Actual BOE 
    boes.Add(new LogBOEViewModel() 
    { 
     LogDate = criteriaDate, 
     BOEActual = GetRandomDouble(random, 100, 1000), 
     BOEForecast = GetRandomDouble(random, 100, 1000) 
    }); 
} 

double GetRandomDouble(Random random, double min, double max) 
{ 
    return min + (random.NextDouble() * (max - min)); 
} 

In questo modo si avere la garanzia che otterrai diversi valori doppi.

0

Se è necessario un numero casuale nell'intervallo [double.MinValue; double.MaxValue]

// Because of: 
double.MaxValue - double.MinValue == double.PositiveInfinity 

// This will be equals to NaN or PositiveInfinity 
random.NextDouble() * (double.MaxValue - double.MinValue) 

Usa invece:

public static class RandomExtensions 
{ 
    public static double NextDoubleInMinMaxRange(this Random random) 
    { 
     var bytes = new byte[sizeof(double)]; 
     var value = default(double); 
     while (true) 
     { 
      random.NextBytes(bytes); 
      value = BitConverter.ToDouble(bytes, 0); 
      if (!double.IsNaN(value) && !double.IsInfinity(value)) 
       return value; 
     } 
    } 
} 
+1

Buon punto, ma questa proposta si traduce in una distribuzione distorta come nel secondo esempio qui https://stackoverflow.com/a/3365388/3922292 –