Генерация взвешенного случайного числа в C # - PullRequest
7 голосов
/ 06 октября 2009

Вопрос

Как я могу случайным образом сгенерировать одно из двух состояний, с вероятностью, что «красный» будет генерироваться в 10% случаев, а «зеленый» - в 90% случаев?

Фон

Каждые 2 секунды мигает зеленый или красный индикатор.

Эта последовательность будет продолжаться в течение 5 минут.

Общее количество миганий должно быть 300.

Ответы [ 8 ]

33 голосов
/ 06 октября 2009

Random.NextDouble возвращает число от 0 до 1, поэтому должно работать следующее:

if (random.NextDouble() < 0.90)
{
    BlinkGreen();
}
else
{
    BlinkRed();
}
7 голосов
/ 06 октября 2009

Или

Random rg = new Random();

int n = rg.Next(10); 
if(n == 0) {
    // blink red
}
else {
    // blink green
}

или

Random rg = new Random();

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

Это работает, потому что Random.Next(int maxValue) возвращает равномерно распределенное целое число в [0, maxValue), а Random.NextDouble возвращает равномерно распределенное double в [0, 1).

3 голосов
/ 06 октября 2009
public class NewRandom
{
    private static Random _rnd = new Random();
    public static bool PercentChance(int percent)
    {
        double d = (double)percent / 100.0;
        return (_rnd.NextDouble() <= d);
    }
}

Для использования:

if (NewRandom.PercentChance(10))
{
    // blink red
}
else
{
    // blink green
}
3 голосов
/ 06 октября 2009

Другие ответы обязательно сработают, если вам нужно случайное распределение, которое благоприятствует 90% зеленого.

Однако, если вам нужен точный дистрибутив, будет работать что-то подобное:

void Main()
{
    Light[] lights = new Light[300];
    int i=0;
    Random rand = new Random();
    while(i<270)
    {
        int tryIndex = rand.Next(300);
        if(lights[tryIndex] == Light.NotSet)
        {
            lights[tryIndex] = Light.Green;
            i++;
        }
    }
    for(i=0;i<300;i++)
    {
        if(lights[i] == Light.NotSet)
        {
            lights[i] = Light.Red;
        }
    }

    //iterate over lights and do what you will
}


enum Light
{
    NotSet,
    Green,
    Red
}
1 голос
/ 06 октября 2009

Полагаю, у вас отключена часть времени (поэтому этот код не решает эту проблему). При условии «хорошего» деления это даст 10% красного и 90% зеленого. Если точность не важна, у ответа Майкла уже есть мой голос.

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();
    }
}
1 голос
/ 06 октября 2009

Опираясь на ответ Михаэля, но добавив дополнительный контекст из вопроса:

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);
    }
}
0 голосов
/ 06 октября 2009

Если вы хотите, чтобы это выглядело случайным образом, вы можете использовать shuffle bag

http://web.archive.org/web/20111203113141/http://kaioa.com:80/node/53

и

Необходим предсказуемый генератор случайных чисел

Таким образом, период мигания должен выглядеть более естественно, и вы можете просто реализовать ограниченное количество миганий.

0 голосов
/ 06 октября 2009
var random = new Random();
for (var i = 0; i < 150; ++i) {
  var red = random.Next(10) == 0;
  if (red)
    // ..
  else
    // Green
}

random.Next(10) случайным образом вернет числа 0..9 и с вероятностью 10% вернет 0. 0. 1003 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...