7
votes

Génération de nombres aléatoires pondérés en C #

Question

Comment puis-je générer aléatoirement l'un des deux états, la probabilité de «rouge» étant générée 10% du temps et «vert» généré 90% du temps?

fond

Tous les 2 seconde soit un feu vert ou rouge clignoteront.

Cette séquence continuera pendant 5 minutes.

Le nombre total d'occurrences d'une lumière clignotante doit être de 300.


2 commentaires

Avez-vous besoin que les résultats soient tels que, hors de vos 300 clignotements de lumière, exactement 30 sont rouges et 270 sont verts? Aucune des réponses jusqu'à présent affichée le fera (sauf par hasard, ironiquement).


Si tel est le cas, voir cette question: Stackoverflow.com/questions/ 910215 / ...


8 Réponses :


7
votes

soit

Random rg = new Random();

double value = rg.NextDouble();
if(value < 0.1) {
    // blink red
}
else {
    // blink green
}


2 commentaires

Si ensuite (int maxvalue) retourner dans la plage [0, maxvalue], alors vous voulez sûrement maxvalue = 9? 10% est 1 sur 10, pas 1 sur 11.


@Krik Broadhurst: Notez que le bon symbole sur [0, maxvalue) est un ')' et non un ']' . Cela signifie que la valeur extrême ( maxvalue ) n'est pas incluse dans la plage. Ainsi, [0, maxvalue) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} .



33
votes

Random.NextDouble retourne un nombre compris entre 0 et 1, les suivants doivent donc fonctionner:

if (random.NextDouble() < 0.90)
{
    BlinkGreen();
}
else
{
    BlinkRed();
}


8 commentaires

+1 Je suis confronté à un problème similaire au dos. C'est la solution la plus élégante que j'ai vue.


Cela fonctionne définitivement si OP peut utiliser une distribution aléatoire que favorise 90% vert.


La classe aléatoire est basée sur le temps, dans la plupart des cas, elle est suffisamment aléatoire. Pour plus de détails: JAPIKSE.BLOGSPOT.COM/2008/10/ Numéro aléatoire-in-C.html


Je crois quels Rex se réfèrent à ce que cela ne soit pas garanti de créer une distribution de 90/10. Il est possible (bien que incroyablement improbable), il cligna un clin d'œil à 100% du temps. Je ne sais pas si exactement 90% était ce que l'affiche originale prévue - la question a été fortement modifiée et que sa signification peut avoir changé.


+1 pour une solution très élégante. Notez également que cela ne garantit pas de générer une distribution de 90% à 10% tout le temps spécialement lorsque vous appelez cette routine à plusieurs reprises en très peu de temps.


En réalité, si la fonction de cette réponse inclut également la ligne initiale présumée aléatoire aléatoire = nouveau aléatoire (); (comme dans la plupart des autres exemples ici), et la fonction est ensuite appelée à plusieurs reprises dans un < Code> pour boucle, vous obtiendrez un résultat surprenant et indésirable. Cela se produira car le constructeur vide pour des graines aléatoires () le générateur avec le temps système, et donc NextDouble () reviendra exactement la même valeur si une méthode telle que celle-ci est appelée à quelques millisecondes. Voir ma réponse pour un moyen d'éviter ce problème potentiel.


Exécutez ce code à partir d'un bouton Cliquez ou autre chose pour voir le problème pour vous-même: pour (int i = 0; i <20; i ++) {RND aléatoire = nouveau aléatoire (); System.diagnostics.debug.print (rnd.nextdouble (). Tostring ());}


0,90 devrait être jeté à un double. Comme ceci: 0.90d



3
votes

Les autres réponses fonctionneront certainement si vous avez besoin d'une distribution aléatoire que favorise 90% de vert.

Cependant, si vous avez besoin d'une distribution , quelque chose comme ça Travaillera: xxx


3 commentaires

Je pense que vous avez un bug - il devrait être "int fyindex = rand.next (300);", sinon vous n'en trouvez jamais de vert à l'une des 270 premières lumières.


Ce serait beaucoup plus efficace si votre première boucle était tandis que (i <30) et vous définissez la valeur sur lumière.red .


@Musi true. Je pourrais également simplement avoir la valeur par défaut de la lumière verte et avoir une boucle à changer en rouge. Je pensais que c'était un peu plus facile à comprendre.



0
votes
var random = new Random();
for (var i = 0; i < 150; ++i) {
  var red = random.Next(10) == 0;
  if (red)
    // ..
  else
    // Green
}
random.Next(10) will randomly return the numbers 0..9 and there is 10% chance of it returning 0.

0 commentaires

3
votes
if (NewRandom.PercentChance(10))
{
    // blink red
}
else
{
    // blink green
}

0 commentaires

1
votes

Bâtiment sur Michaels Répondre, mais ajoutant un autre contexte de la question:

public static void PerformBlinks()
{
    var random = new Random();
    for (int i = 0; i < 300; i++)
    {
        if (random.Next(10) == 0)
        {
            BlinkGreen();
        }
        else
        {
            BlinkRed();
        }
        // Pause the thread for 2 seconds.
        Thread.Sleep(2000);
    }
}


4 commentaires

Salut Musignèse. Peut-être souhaiteriez-vous fournir un échantillon de code qui fait une pause du fil pendant 2 secondes, mais n'utilise pas de thread.sleep?


Il voulait probablement dire qu'il serait préférable d'utiliser une minuterie que de dormir le fil.


Mais en toute justice pour vous, Scott, vous ne pouvez pas dire à la question de savoir si le sommeil serait un problème ou non.


@fantius: Oui, je voulais utiliser une minuterie plutôt que sur le thread.sleep (n). Utiliser WHIP.SLEEP pour atteindre le timing est une mauvaise pratique, quels que soient les détails de cette question.



1
votes

Je suppose que vous avez la partie chronométrée (ce code n'entraîne donc pas cela). En supposant que la division «Nice», cela générera 10% de rouges et 90% de légumes verts. Si l'exactitude n'est pas importante, la réponse de Michael a déjà mon vote.

static void Main(string[] args)
{
    int blinkCount = 300, redPercent = 10, greenPercent = 90;
    List<BlinkObject> blinks = new List<BlinkObject>(300);

    for (int i = 0; i < (blinkCount * redPercent / 100); i++)
    {
        blinks.Add(new BlinkObject("red"));
    }

    for (int i = 0; i < (blinkCount * greenPercent / 100); i++)
    {
        blinks.Add(new BlinkObject("green"));
    }

    blinks.Sort();

    foreach (BlinkObject b in blinks)
    {
        Console.WriteLine(b);
    }
}

class BlinkObject : IComparable<BlinkObject>
{
    object Color { get; set; }
    Guid Order { get; set; }

    public BlinkObject(object color)
    {
        Color = color;
        Order = Guid.NewGuid();
    }

    public int CompareTo(BlinkObject obj)
    {
        return Order.CompareTo(obj.Order);
    }

    public override string ToString()
    {
        return Color.ToString();
    }
}


0 commentaires

0
votes

Si vous voulez que ceux-ci viennent d'apparaître aléatoires, vous voudrez peut-être implémenter Sac de lecture

http: //web.archive .org / Web / 20111203113141 / http: //kaioa.com: 80 / nœud / 53

et

besoin de générateur aléatoire prévisible

De cette façon, la période clignotante doit être plus naturelle et vous pouvez simplement mettre en œuvre le nombre restreint de clignotements.


0 commentaires