要求:输入人数和金额总数(人数1-50,金额数不大于200,同时保证每个人至少0.01元),打印每个红包的金额数,要求金额分布要相对均匀,不允许大金额的红包集中在同一个区域,不允许金额数目都递增或递减的规律变化,也不允许有太大的差距,如199。2 和0.8….
代码实现过程:利用srand()生成伪随机数的种子,考虑到每次运行的红包分布都要不同,所以使用时间作为 种子,即srand((unsigned int)time(0));
在代码运行过程中rand()生成0-32767的随机数。
由于每个人获得的金额最多为三位数,同时为带小数的数值,因此,rand()生成的随机数需要除以100.0会更符合我们的要求。
又由于金额分布需要相对均匀,于是便想到了平均数,由于不允许相同,便利用平均数(剩下的钱除以剩下的人),结合题目给出的金额要求限定了一个区间。只要随机数除以100.0之后的值在区间内,即作数!否则,忽略这个随机数,不计入红包金额中。
p = rand() / 100.0;
p >= 0.01&&p < (m / n) * 2 && p<m-(n-1)*0.01
同时,在测试运行时会发现,在5个人,金额总数为0.06的情况下,总会是最后一个人拿到0.02元,也就是不符合随机分配的要求;以及在5个人,0.05元的情况下,经常会出现打印时只能打印2个人,3个人的红包金额数,主要是由于在后面的随机数中,要达到我说限定的要求的概率太小了。因此,我把这两种情况分离出来进行了讨论。
解决这个问题之后,代码就不难了。
下面贴上完整的代码
#include <iostream>
#include <stdlib.h> //srand/rand函数
#include <time.h> //time函数
#include<iomanip>
using namespace std;
int main()
{
int n, imax = 1;;
double m,p,max=0;
while (1)
{
cout << "请输入人数n[1,50]以及金额m[0.01,200]: ";
cin >> n >> m;
if (m >= (0.01*n)&&m<=200&&n<=50&&n>=1)
break;
}
srand((unsigned int)time(0));
cout << endl << "每个人的红包金额为:" << endl;
if (n == 1)
cout << m << endl;
else if (m == 0.01*(n + 1))
{
int index = rand() % n + 1;
for(int i=1;i<=n;i++)
if(i==index)
cout<<"第"<<i<<"个人抢到的红包金额为:0.02元" << endl;
else
cout << "第" << i << "个人抢到的红包金额为:0.01元" << endl;
}
else if(m==0.01*n)
for (int i = 1; i <= n; i++)
cout << "第" << i << "个人抢到的红包金额为:0.01元" << endl;
else
{
int c = n;
for (int i=0;n >1;)
{
p = rand() / 100.0;
if (p >= 0.01&&p < (m / n) * 2 && p<m-(n-1)*0.01)//为均衡几率,以与平均数相关的数据来做阈值,同时,为了防止数据呈前大后小的情况,*2
{
i++;
cout << "第"<<i<<"个人抢到的红包金额为:"<<p<<"元" << endl;
m = m - p;
n--;
if (p > max)
{
max = p;
imax = i;
}
}
}
cout << "第" << c << "个人抢到的红包金额为:" << m << "元" << endl;
if (m > max)
{
max = m;
imax = c;
}
cout<< "第" << imax << "个人是手气王\n抢到的红包金额为:" << max << "元" << endl;
}
return 0;
}
仍旧存在的问题:金额为0.07,5个人,不会有0.03元的红包