簡體   English   中英

概率和隨機數生成器

[英]Probability and Random number generator

我正在研究一個涉及概率和隨機數生成器的問題,我認為我與之接近,但需要敲定最后一件事。 我有一個大理石袋,可以在其中輸入不同顏色的大理石數量。 含義紅色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個橙色,需要做些什么才能解密來選擇藍色或橙色。

就個人而言,我根本不會使用double我只會選擇0(含)和大理石總數(不含)之間的隨機整數 有效地,您將用數字“標記”每個大理石,然后根據隨機整數確定選擇了哪個大理石。 例如:

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)。

我也避免使用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秒鍾內生產並分類一個裝有180 萬個大理石的袋子。

問題是當前您所有的數字都在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告訴您的答案 不需要標准化值的步驟(用MarbleCnt划分),而不是標准化您的值在0和1之間,然后選擇0和1之間的隨機值,只需將您的值保持在0到22,然后選擇0到22之間的隨機數即可。喬恩在回答中表示。

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
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM