可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
Random.NextDouble returns a number between 0 and 1, so the following should work:
if (random.NextDouble() < 0.90)
{
BlinkGreen();
}
else
{
BlinkRed();
}
回答2:
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)
.
回答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
}
回答4:
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
}
回答5:
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);
}
}
回答6:
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();
}
}
回答7:
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.
回答8:
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.