7

Question

How can I randomly generate one of two states, with the probability of 'red' being generated 10% of the time, and 'green' being generated 90% of the time?

Background

Every 2 second either a green or a red light will blink.

This sequence will continue for 5 minutes.

The total number of occurrences of a blinking light should be 300.

2
  • 1
    Do you need the results to be such that, out of your 300 light blinks, exactly 30 are red and 270 are green? None of the answers so far posted will do that (except by chance, ironically). Commented Oct 5, 2009 at 20:42
  • 3
    If so, see this question: stackoverflow.com/questions/910215/… Commented Oct 5, 2009 at 20:47

8 Answers 8

33

Random.NextDouble returns a number between 0 and 1, so the following should work:

if (random.NextDouble() < 0.90) { BlinkGreen(); } else { BlinkRed(); } 
Sign up to request clarification or add additional context in comments.

8 Comments

+1 I faced a similar problem a while back. This is the most elegant solution I've seen.
This definitely works if OP can use a random distribution that favors 90% green.
The Random class is based on time, in most cases it's random enough. For more details: japikse.blogspot.com/2008/10/random-numbers-in-c.html
I believe what Rex is referring to is that this isn't guaranteed to create a 90/10 distribution. It is possible (though incredibly unlikely) it will blink red 100% of the time. I'm not sure if exactly 90% was what the original poster intended - the question has been heavily edited and its meaning may have changed.
+1 for very elegant solution. Also note that this does not guarantee to generate 90%-10% distribution all the time specially when you are calling this routine repeatedly in very short amount of time.
|
7

Either

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

or

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

This works because Random.Next(int maxValue) returns a uniformly distributed integer in [0, maxValue) and Random.NextDouble returns a uniformly distributed double in [0, 1).

2 Comments

If Next(int maxValue) return in the range [0,maxValue] then surely you want maxValue = 9? 10% is 1 out of 10, not 1 out of 11.
@Krik Broadhurst: Note that the right symbol on [0, maxValue) is a ')' and not a ']'. This means that the extreme value (maxValue) is not included in the range. Thus, [0, maxValue) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.
3
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); } } 

To use:

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

Comments

3

The other answers will definitely work if you need a random distribution that favors 90% green.

However, if you need a precise distribution, something like this will work:

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 } 

3 Comments

I think you have a bug - it should be "int tryIndex = rand.Next(300);", otherwise you're only ever assigning Green to one of the first 270 lights.
This would be a lot more efficient if your first loop was while (i < 30) and you set the value to Light.Red. </nitpicking>
@Musi true. I could also just have the default value of Light be Green and have one loop to change to red. I thought this was a little easier to understand.
1

Building on Michaels answer, but adding further context from the 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 Comments

Hi MusiGenesis. Perhaps you would like to provide a code sample that pauses the thread for 2 seconds, but does not use Thread.Sleep ?
He probably meant that it would be better to use a timer than to sleep the thread.
But in fairness to you, Scott, you can't tell from the question whether sleeping would be a problem or not.
@fantius: yes, I meant use a timer rather than Thread.Sleep(n). Using Thread.Sleep to achieve timing is a bad practice, regardless of any details of this question.
1

I'm guessing you have the timing part down (so this code doesn't address that). Assuming "nice" division, this will generate 10% reds and 90% greens. If the exactness isn't important, Michael's answer already has my 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(); } } 

Comments

0
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.

Comments

0

If you want these just to look random, you might want to implement shuffle bag

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

and

Need for predictable random generator

This way the blinking period should look more natural and you can simply implement the restricted number of blinks.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.