大家帮我看看,逻辑是否正确.
786人参选,要求选出203人,默认测试10000次,计算5连号出现的概率
checkBoxIncludeHigher默认是选中状态,也就是 出现两个五连号或者出现六连号\七连号等也包括在五连号中.
如果不选中,则计算仅出现一个五连号的概率.
测试次数10000次的话,计算是很快的,但10000次的结果稳定性差一些.如果是10万次的话,要数秒(小于10秒),但稳定性好.我根据概率公式计算应该是86.6%(公式参见天涯杂谈),可是模拟结果确是48.x%,疑惑中,故请教各位高手private void buttonBeginTest_Click(object sender, RoutedEventArgs e)
{
int Total=0,Draw=0,N=0,TestTime=0; try
{
Total=int.Parse(txtTotal.Text); //786
Draw=int.Parse(txtDraw.Text); //203
N=int.Parse(txtN.Text); //5
TestTime=int.Parse(txtTestTime.Text); //10000
}
catch
{
MessageBox.Show("数据输入有错误,请检查");
return;
} if (Draw > Total || N > Draw || N<=0)
{
MessageBox.Show("数据输入有错误,请检查");
return;
} //Now begin test
int NOccurs = 0;//N连号出现的次数
Random r = new Random();
for (int i = 0; i < TestTime; i++)
{
//初始化被选数组
int[] t = new int[Total];
for (int j = 0; j < Total; j++)
{
t[j] = j + 1;
}
int[] d = new int[Draw];
//打乱原数组
for (int j = 1; j < Total; j++)
{
//swap
int temp = t[j];
int b = r.Next() % (j + 1);
t[j] = t[b];
t[b] = temp;
} //打乱次序后的原数组复制到d中,就是被选出的号
for (int j = 0; j < Draw; j++)
{
d[j] = t[j];
} //d中选出的数从小到大排序
Array.Sort(d); //连号测试
int NTimes = 0;//N连号出现次数
int NPlusTimes = 0;//N+1连号出现的次数 for (int j = 0; j < Draw - N + 1; j++)
{
if (d[j + N -1] == d[j] + N -1)
{
NTimes++;
if (NTimes>1)
break;
}
}
if(!(bool)checkBoxIncludeHigher.IsChecked)
for (int j = 0;j < Draw - N ; j++)
{
if (d[j + N] == d[j] + N)
{
NPlusTimes++;
break;
}
}
if ((bool)checkBoxIncludeHigher.IsChecked)
{
if (NTimes > 0) NOccurs++;
}
else
{
if (NTimes == 1 && NPlusTimes == 0) NOccurs++;
}
}
lblResult.Content = N.ToString() + "连号出现次数:" + NOccurs.ToString() +
",概率=" + (NOccurs / (double)TestTime).ToString("P2") ;
}
786人参选,要求选出203人,默认测试10000次,计算5连号出现的概率
checkBoxIncludeHigher默认是选中状态,也就是 出现两个五连号或者出现六连号\七连号等也包括在五连号中.
如果不选中,则计算仅出现一个五连号的概率.
测试次数10000次的话,计算是很快的,但10000次的结果稳定性差一些.如果是10万次的话,要数秒(小于10秒),但稳定性好.我根据概率公式计算应该是86.6%(公式参见天涯杂谈),可是模拟结果确是48.x%,疑惑中,故请教各位高手private void buttonBeginTest_Click(object sender, RoutedEventArgs e)
{
int Total=0,Draw=0,N=0,TestTime=0; try
{
Total=int.Parse(txtTotal.Text); //786
Draw=int.Parse(txtDraw.Text); //203
N=int.Parse(txtN.Text); //5
TestTime=int.Parse(txtTestTime.Text); //10000
}
catch
{
MessageBox.Show("数据输入有错误,请检查");
return;
} if (Draw > Total || N > Draw || N<=0)
{
MessageBox.Show("数据输入有错误,请检查");
return;
} //Now begin test
int NOccurs = 0;//N连号出现的次数
Random r = new Random();
for (int i = 0; i < TestTime; i++)
{
//初始化被选数组
int[] t = new int[Total];
for (int j = 0; j < Total; j++)
{
t[j] = j + 1;
}
int[] d = new int[Draw];
//打乱原数组
for (int j = 1; j < Total; j++)
{
//swap
int temp = t[j];
int b = r.Next() % (j + 1);
t[j] = t[b];
t[b] = temp;
} //打乱次序后的原数组复制到d中,就是被选出的号
for (int j = 0; j < Draw; j++)
{
d[j] = t[j];
} //d中选出的数从小到大排序
Array.Sort(d); //连号测试
int NTimes = 0;//N连号出现次数
int NPlusTimes = 0;//N+1连号出现的次数 for (int j = 0; j < Draw - N + 1; j++)
{
if (d[j + N -1] == d[j] + N -1)
{
NTimes++;
if (NTimes>1)
break;
}
}
if(!(bool)checkBoxIncludeHigher.IsChecked)
for (int j = 0;j < Draw - N ; j++)
{
if (d[j + N] == d[j] + N)
{
NPlusTimes++;
break;
}
}
if ((bool)checkBoxIncludeHigher.IsChecked)
{
if (NTimes > 0) NOccurs++;
}
else
{
if (NTimes == 1 && NPlusTimes == 0) NOccurs++;
}
}
lblResult.Content = N.ToString() + "连号出现次数:" + NOccurs.ToString() +
",概率=" + (NOccurs / (double)TestTime).ToString("P2") ;
}
如果连续1万次执行buttonBeginTest_Click,那么产生的随机数很多是连续相同的。
Random r的实例化最好是在方法体外。
实际应该就是48.x%的概率.
具体计算方法在mathe论坛有一个14连号的计算帖子里有.2楼说的我连续一万次执行这个方法,没有仔细看我的程序,是在方法里for这个循环一万次之前初始化Random.不管怎么说,来我的帖子回复的都给分.