2009-06-30 11 views
99

Est-il possible de générer un nombre aléatoire entre 2 doubles?Nombre aléatoire entre 2 nombres doubles

Exemple:

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

Alors je l'appelle avec les éléments suivants:

double result = GetRandomNumber(1.23, 5.34); 

Toutes les pensées seraient appréciés.

Répondre

241

Oui. Random.NextDouble renvoie un double entre 0 et 1. Vous multipliez ensuite par la plage dans laquelle vous devez entrer (différence entre le maximum et le minimum), puis ajoutez-le à la base (minimum).

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

Le code réel doit être un membre statique. Cela permettra d'économiser le coût de création du générateur de nombres aléatoires, et vous permettra d'appeler GetRandomNumber très fréquemment. Puisque nous initialisons un nouveau RNG avec chaque appel, si vous appelez assez vite pour que l'heure du système ne change pas entre les appels, le RNG sera placé avec exactement le même horodatage, et générera le même flux de nombres aléatoires.

+24

Il suffit de regarder si vous appelez GetRandomNumber() dans une boucle comme il va générer la même valeur à plusieurs reprises –

+0

@John - Bon point, j'ai ajouté ceci à ma réponse. – Michael

+0

parfait! C'est ce que je cherchais. Merci beaucoup – CodeLikeBeaker

6

L'approche la plus simple serait simplement de générer un nombre aléatoire entre 0 et la différence des deux nombres. Puis ajoutez le plus petit des deux nombres au résultat.

3

Vous pouvez utiliser le code comme ceci:

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

Whow, un magique 'randomizer var' est apparu !! – Lucas

2

Vous pouvez le faire:

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 propos de générer le même nombre aléatoire si vous l'appelez dans une boucle une solution astucieuse est de déclarer la Nouvel objet Random() en dehors de la boucle en tant que variable globale.

Notez que vous devez déclarer votre instance de la classe Random en dehors de la fonction GetRandomInt si vous allez l'exécuter en boucle.

"Pourquoi est-ce?", Demandez-vous. Eh bien, la classe Random génère réellement des nombres pseudo-aléatoires, avec le "seed" pour le randomizer étant l'heure du système. Si votre boucle est suffisamment rapide, l'heure de l'horloge du système n'apparaîtra pas différemment du randomizer et chaque nouvelle instance de la classe Random commencera avec la même graine et vous donnera le même nombre pseudo-aléatoire.

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

+0

Ceci est mieux adapté comme commentaire, car il ne tente même pas de répondre à la question réelle de OP. –

28

Johnny5 a suggéré la création d'une méthode d'extension. Voici un exemple de code plus complet montrant comment vous pourriez faire ceci:

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

Maintenant, vous pouvez l'appeler comme si elle était une méthode sur la Random classe:

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

Notez que vous ne devez pas créer beaucoup de nouveaux objets Random dans une boucle, car il est probable que vous obteniez la même valeur plusieurs fois de suite. Si vous avez besoin de beaucoup de nombres aléatoires, créez une instance de Random et réutilisez-la.

1

Que se passe-t-il si l'une des valeurs est négative? Ne serait-une meilleure idée être:

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

Merci pour les idées supplémentaires. Très utile à une vieille question :) – CodeLikeBeaker

+5

Je pense que le 'Math.Abs ​​()' est redondant. Puisque vous vous êtes assuré que 'min> = max', alors' max - min' doit de toute façon être un nombre non négatif. –

0
Random random = new Random(); 

double NextDouble(double minimum, double maximum) 
{ 

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

} 
4

attention: si vous générez la random dans une boucle comme par exemple for(int i = 0; i < 10; i++), ne mettez pas la déclaration new Random() dans la boucle.

De MSDN:

la génération de nombres aléatoires commence à partir d'une valeur de départ. Si la même graine est utilisée à plusieurs reprises, la même série de nombres est générée. Une façon de produire différentes séquences est de faire en sorte que la valeur de départ dépende du temps, produisant ainsi une série différente avec chaque nouvelle instance de Random. Par défaut, le constructeur parameterless de la classe aléatoire utilise l'horloge système pour générer sa valeur de départ ...

donc basée sur ce fait, faire quelque chose comme:

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

Faire de cette façon vous avoir la garantie que vous aurez différentes valeurs doubles.

0

Si vous avez besoin d'un nombre aléatoire dans la plage [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) 

utiliser à la place:

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

Bon point, mais cette proposition entraîne une distribution asymétrique comme dans le deuxième exemple ici https://stackoverflow.com/a/3365388/3922292 –

Questions connexes