[英]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.