概率和随机数发生器

时间:2015-04-01 00:52:36

标签: c#

我正在研究一个涉及概率和随机数发生器的问题,我相信我很接近,但需要帮助敲出最后一件事。我有一个大理石袋,我将在其中输入不同颜色的大理石的数量。含义红色10绿色5蓝色5橙色3.我必须推断每个彩色大理石的概率,然后根据该概率随机生成多个大理石。到目前为止,我可以计算概率

  int MarbleCnt = red + green + blue + orange;
  double probRed = (double)red / MarbleCnt;
  double probGreen = (double)green / MarbleCnt;
  double probBlue = (double)blue / MarbleCnt;
  double probOrange = (double)orange / MarbleCnt;

然后我计划使用Random().NextDouble来解释选择哪个大理石这是我的代码:

for (int i = 0; i < 10; i++) {
    double randNum = mRandom.NextDouble();             
    if (0 <= randNum && randNum < probRed) { probArr[i] = RED_MARBLE; }
    else if (probRed <= randNum && randNum < probGreen) { probArr[i] = GREEN_MARBLE; }
    else if (probGreen <= randNum && randNum < probBlue) { probArr[i] = BLUE_MARBLE; }
    else  { probArr[i] = ORANGE_MARBLE; }
}

我的问题是,如果我有相同数量的弹珠,我该怎么办,意思是我有10个红色,5个蓝色和5个橙色,我需要做什么才能解密选择蓝色或橙色。

4 个答案:

答案 0 :(得分:4)

就个人而言,我根本不会使用double - 我只需在0(含)和大理石总数之间挑选一个随机整数(独家) )。实际上,你是&#34;标签&#34;每个大理石都有一个数字,然后根据随机整数计算出哪个大理石被挑选出来。例如:

MarbleColor PickMarble
    (Random rng, int redCount, int greenCount, int blueCount, int orangeCount)
{
    int index = rng.Next(redCount + greenCount + blueCount + orangeCount);
    if (index < redCount)
    {
        return MarbleColor.Red;
    }
    if (index < redCount + greenCount)
    {
        return MarbleColor.Green;
    }
    if (index < redCount + greenCount + blueCount)
    {
        return MarbleColor.Blue;
    }
    return MarbleColor.Orange;
}

这与您使用双打的方法基本相同,但更容易理解(IMO)。

答案 1 :(得分:1)

我也会避免使用double。虽然从处理概率看起来很自然,但你会发现最终编写的代码很难证明其正确性和调试性。

最好尝试更加离散地对大理石袋进行建模。

我会这样做:

var red = 10;
var green = 5;
var blue = 5;
var orange = 2;

var rnd = new Random();

var bag =
    Enumerable.Repeat(RED_MARBLE, red)
        .Concat(Enumerable.Repeat(GREEN_MARBLE, green))
        .Concat(Enumerable.Repeat(BLUE_MARBLE, blue))
        .Concat(Enumerable.Repeat(ORANGE_MARBLE, orange))
        .OrderBy(m => rnd.Next())
        .ToList();

我现在有一个均匀洗净的大理石袋,我可以从中挑选出来以模拟从袋中取出大理石。

虽然这不像纯数学方法那样高效,但仍然非常快。我可以使用这种方法在1秒钟内制作和分类一个包含1.8 <百万> >弹珠的袋子。

答案 2 :(得分:1)

问题是目前你的所有数字都在0和标准化(0到1之间)的概率之间。看看你的概率变量的值

int red = 10;
int green = 5;
int blue = 5;
int orange = 3;
int MarbleCnt = red + green + blue + orange;
double probRed = (double)red / MarbleCnt;
double probGreen = (double)green / MarbleCnt;
double probBlue = (double)blue / MarbleCnt;
double probOrange = (double)orange / MarbleCnt;

Console.WriteLine("Red: " + probRed);       
Console.WriteLine("Green: " + probGreen);       
Console.WriteLine("Blue: " + probBlue);     
Console.WriteLine("Orange: " + probOrange);

此输出

Red: 0.434782608695652
Green: 0.217391304347826
Blue: 0.217391304347826
Orange: 0.130434782608696

你需要做的是你的条件需要加上以前的条件,这可以抵消它们,你可以分辨出你落入哪个“桶”。

for (int i = 0; i < 10; i++) 
{
    double randNum = mRandom.NextDouble();             
    if (randNum < probRed) 
    { 
        probArr[i] = RED_MARBLE; 
    }
    else if (randNum < (probRed + probGreen)) 
    {
        probArr[i] = GREEN_MARBLE; 
    }
    else if (randNum < (probRed + probGreen + probBlue)) 
    {
        probArr[i] = BLUE_MARBLE; 
    }
    else  
    { 
        probArr[i] = ORANGE_MARBLE; 
    }
}

如果这段代码看起来很熟悉,这正是Jon告诉你在his answer中做的事情。标准化值(除以MarbleCnt)的步骤是不必要的,而不是将值归一化到0和1之间,然后选择介于0和1之间的随机值,只需将值保留为0到22然后选择0之间的随机数。而Jon则在他的回答中描述了这一点。

答案 3 :(得分:-3)

char RandomCharacter()
{ 
  /* as the denominator of the probability is 7 hence we will generate a random number between 1-7 */
  int RandNo = rand()%7+1;

  // now distribute the distribution with respect to probability
  if(RandNo<=4 and RandNo>=1) {
    return '*'; // 4/7 chances are to lie here
  }
  if(RandNo<=6) {
    return '#'; // 2/7 chances are to lie in this range now
  } else {
    return '@'; // 1/7 chances are remaining
  }
}