111,125
社区成员
发帖
与我相关
我的任务
分享
//总人数
int totalNum=5000;
//总金额
decimal totalAmount=6000;
//最小值
decimal minMoney=1;
//最大值
decimal maxMoney=2;
//平均点范围
var avgMoney = (maxMoney - minMoney) / 4;
//分配金额
decimal sendMoney = 0;
int i = 0;
while (i < totalNum)
{
//当前数量
var iNum = totalNum - i;
//平均值
var avgAmount = totalAmount / iNum;
//当最小值与当前数量的乘积等于当前总金额时,分配金额取最小值
if (minMoney * iNum == totalAmount)
{
sendMoney = minMoney;
}
//当最大值与当前数量的乘积等于当前总金额时,分配金额取最大值
else if (maxMoney * (totalNum - i) == totalAmount)
{
sendMoney = maxMoney;
}
else {
//最小值
var min = Math.Max(minMoney, avgAmount - avgMoney);
//最大值
var max = Math.Min(maxMoney, avgAmount + avgMoney);
//随机提取分配金额
var seed = Guid.NewGuid().GetHashCode() + i;
Random r = new Random(seed);
sendMoney = Convert.ToDecimal(r.Next(Convert.ToInt32(min * 100), Convert.ToInt32(max * 100))) / 100;
}
//减去当前分配金额后的总金额
var minusAmount = totalAmount - sendMoney;
if ((iNum - 1) > 0 && (minMoney * (iNum - 1)) <= minusAmount)
{
if ((maxMoney * (iNum - 1)) < minusAmount)
{
//如果剩下的总金额大于实际最大分配金额,则将当前分配金额加上取余的数
sendMoney = sendMoney + minusAmount % (maxMoney * (iNum - 1));
}
//总金额减掉当前分配金额
totalAmount -= sendMoney;
i++;
}
//最后分配剩下的所有钱
else if ((iNum - 1) == 0)
{
sendMoney = totalAmount;
i++;
}
}

while (totalMoney > 0)
{
int i = rnd.Next(0, counter);
double money = rnd.Next(minValue, maxValue) / 100.0;
money = totalMoney - money < 0 ? totalMoney : money;//如果余额不足,则仅分余额
if (perMoney[i] + money <= maxMoney)//不能超过上限
{
perMoney[i] += money;
totalMoney -= money;
}
}
i的值随机获得,不再需要初始值!如果希望分得再均匀一些可以将maxValue的值再调小一点!
static void Main(string[] args)
{
double totalMoney = 6000;//钱的总数
int counter = 5000;//人数
double baseMoney = 1.0;//每个人分到钱的最小值
double maxMoney = 2.0;//每个人能分到钱的最大值
System.Random rnd = new System.Random();
double[] perMoney = new double[counter];
//给每个人分配基数值的钱,同时调整钱的总数
for(int j = 0; j < counter; j++)
{
perMoney[j] = baseMoney;
totalMoney -= baseMoney;
}
//因为Random.Next产生的是整数,所以放大100倍
int minValue = 0, maxValue = (int)((maxMoney - baseMoney) * 100);
int i = 0;
//分剩下的钱
while (totalMoney > 0)
{
double money = rnd.Next(minValue, maxValue) / 100.0;
money = totalMoney - money < 0 ? totalMoney : money;//如果余额不足,则仅分余额
perMoney[i] += money;
i++;
totalMoney -= money;
if(i>=counter && totalMoney>0) //如果每个人都分了还有剩余,则从头再把剩下的钱分了,也可以随机选一个人开始分
{
minValue = 0;
maxValue = 100;
i = 0;
}
}
foreach(double m in perMoney)
{
Console.Write(m.ToString());
Console.Write("\t");
}
//上面的函数有bug 其实这个也有bug 主要是限制了最大值 就什么都不好说了
private static int GetRedBag(ref int bag, ref int p)
{
var min = 100;
var mid = bag/p;
var max = 201;
var max1 = mid*2 - min;
max = max1 > max ? max : max1;
if (bag / p == min && bag % p == 0)
{
bag -= (max - 1);
p--;
return min;
}
if (bag / p == max - 1 && bag % p==0)
{
bag -= (max - 1);
p--;
return max-1;
}
Random rn = new Random(Convert.ToInt32(Guid.NewGuid().ToString("N").Substring(0,5),16));
var result = rn.Next(min, max);
while (((bag - result) / p < min) || (bag - result) / p > max)
{
result = rn.Next(min, max);
}
bag -= result;
p--;
return result;
}
static void Main(string[] args)
{
var bag = 600000;
var p = 5000;
for (int i = 0; i < p; i++)
{
var redbag = GetRedBag(ref bag, ref p);
Console.Write(redbag+" ");
}
Console.ReadKey();
}
//这样单纯随机数 会导致最后的红包分配不合理 下面在给出一种更合理的方式
private static int GetRedBag(ref int bag, ref int p)
{
var min = 100;
var max = 201;
if (bag/p == min)
{
return min;
}
if (bag / p == max-1)
{
return max;
}
Random rn = new Random(Convert.ToInt32(Guid.NewGuid().ToString("N").Substring(0,5),16));
var result = rn.Next(min, max);
while ((bag - result) / p < min || (bag - result) / p > max)
{
result = rn.Next(min, max);
}
bag -= result;
p--;
return result;
}