问题描述
100元50个人随机生成大于1小于20的随机金额求个代码案例
解决方案
解决方案二:
这个?http://blog.csdn.net/z69183787/article/details/50674531
解决方案三:
这个达不到我想要的效果,我想的是比如100元20个人抢,我可以设置最高的人可以抢到30元最低的人可能抢到0.1元
解决方案四:
你发的这个感觉最高的那么不定额度最低的那个也是不低额度
解决方案五:
以“平均概率”的思路来分配红包,非常无趣,这类创意乏味极了。要分配红包,就要有“扰动”,要有的人特别多、有的人特少,这样的算法才有创意。所以这里的“随即金额”概念,如果你细想,可能是非常不靠谱的需求。
解决方案六:
引用2楼hejianxiong520的回复:
这个达不到我想要的效果,我想的是比如100元20个人抢,我可以设置最高的人可以抢到30元最低的人可能抢到0.1元
是这样的。其实分配过程可以看作是一个“削峰填谷”的过程。你首先给20分随便分配一个数值,分配时除了随机数以外、一定概率下还会乘以“扰动”,最终得到一组数值。然后将这组数值按照其合计与100元的比例,每一个数都乘以这个比例,使得总计是100元。然后要削峰。也就是找到第一个高于20元的,把它的多出来的钱平均分给其它人。反复削峰,直到没有一个人的金额大于20。然后填谷。类似的算法,就是找到第一个金额低于0.1的人,其它人每一个人都贡献一点零头来填它的差额。最后为了将金额全都保留两位小数,你可以编译一遍,用最后一个人(第20个人)来修正因为保留2位小数而造成的总额误差。上述算法中,人员数、总金额、金额下限、金额上限、隔多少人进行扰动、保留1位还是2位小数,这些都应该设置成参数,应该可以随时调整。
解决方案七:
你首先给20分随便分配一个数值-->你首先给20人随便分配一个数值
解决方案八:
我又要搬出这贴了
解决方案九:
引用7楼shingoscar的回复:
我又要搬出这贴了
试了一下,输入最大值3000分的时候,没有一次产生30块钱的结果啊。
解决方案十:
引用8楼sp1234的回复:
Quote: 引用7楼shingoscar的回复:
我又要搬出这贴了试了一下,输入最大值3000分的时候,没有一次产生30块钱的结果啊。
另外,这其实会造成最小值偏多(也就是0.1的值偏多)、同时大于最小值的其它值又是以平均概率分布的。例如这样几组打印结果:0.100.100.100.100.100.100.100.110.110.130.140.311.261.351.822.7720.5422.4523.4424.87合计=100..............按任意键结束0.100.100.100.100.100.100.100.110.110.120.740.991.177.477.669.199.8516.0517.0628.78合计=100..............按任意键结束0.100.100.100.100.100.100.120.160.170.210.411.031.462.673.218.9912.6914.5625.0028.72合计=100..............按任意键结束0.100.100.100.100.100.100.100.100.100.120.170.291.202.462.875.7915.3319.2624.4227.19合计=100..............按任意键结束0.100.100.100.100.100.140.240.390.460.611.302.053.123.937.047.419.2314.9822.9825.62合计=100..............按任意键结束
解决方案十一:
引用9楼sp1234的回复:
Quote: 引用8楼sp1234的回复:
Quote: 引用7楼shingoscar的回复:
我又要搬出这贴了试了一下,输入最大值3000分的时候,没有一次产生30块钱的结果啊。
另外,这其实会造成最小值偏多(也就是0.1的值偏多)、同时大于最小值的其它值又是以平均概率分布的。例如这样几组打印结果:0.100.100.100.100.100.100.100.110.110.130.140.311.261.351.822.7720.5422.4523.4424.87合计=100..............按任意键结束0.100.100.100.100.100.100.100.110.110.120.740.991.177.477.669.199.8516.0517.0628.78合计=100..............按任意键结束0.100.100.100.100.100.100.120.160.170.210.411.031.462.673.218.9912.6914.5625.0028.72合计=100..............按任意键结束0.100.100.100.100.100.100.100.100.100.120.170.291.202.462.875.7915.3319.2624.4227.19合计=100..............按任意键结束0.100.100.100.100.100.140.240.390.460.611.302.053.123.937.047.419.2314.9822.9825.62合计=100..............按任意键结束
我知道啊,最开头不是有一行红色的、很小的话么每份的范围,不能超出平均数太多
解决方案十二:
引用8楼sp1234的回复:
Quote: 引用7楼shingoscar的回复:
我又要搬出这贴了试了一下,输入最大值3000分的时候,没有一次产生30块钱的结果啊。
范围是10-3000,如果随机数是平均分布的,平均2990次才会出现一次
解决方案十三:
腾讯使用正态分布概率,而非平均概率。实际上就是改了一下Random算法,但是这需要输入期望的几个参数,这2、3个正态分布输入参数应该能从“最大最小金额、产生红包个数、需要多少人非常接近最大金额、需要多少人非常接近最小金额”而推导出来。它的结果看起来就不是“很平均的”数值了(除掉所有最小的数值以外),可以调整结果数值的分布。也不一定要生态分布,看起来的计算结果,其实就是要能够对结果进行干扰(来产生趣味性),或者让比较大的数值再多一些,或者让非常小的数值再多一些。
解决方案十四:
比如说,问题假设是:100元分成20分,最小0.1元,最大15元,“看似随机”,但是13元以上的人至少有3个,5元以下但是0.5元以上的人至少有5个。如果能这样编写程序就有意思了。
解决方案十五:
usingSystem;usingSystem.Linq;publicclassTest{publicstaticvoidMain(){//yourcodegoeshereRandomrnd=newRandom();double[]arr=newdouble[50];for(inti=0;i<20;i++)arr[i]=rnd.NextDouble();doubler=2.0/arr.Average();for(inti=0;i<20;i++){arr[i]*=r;Console.Write(arr[i].ToString("0.00")+"");}}}
2.718.982.160.250.868.7610.632.706.941.335.188.185.354.640.876.273.1611.253.296.49
解决方案:
看微信红包的算法就好了
解决方案:
引用15楼hanjun0612的回复:
看微信红包的算法就好了
解决方案:
引用16楼sp1234的回复:
Quote: 引用15楼hanjun0612的回复:
看微信红包的算法就好了
就是一楼给的链接引用1楼zbdzjx的回复:
http://blog.csdn.net/z69183787/article/details/50674531
我个人觉得这种都是算法大于实现。只要知道算法,那实现是不难的。
解决方案:
List<double>list=newList<double>();//100元50个人随机生成大于1小于20的随机金额publicvoidgetRandom(){if(list.Count<50){Randomrd=newRandom();if(list.Max()>20){inta=rd.Next(0,Int32.Parse((list.Max()*100).ToString()));list.Add(a*0.01);list.Add(list.Max()-a*0.01);list.Remove(list.Max());doubletemp=0;for(intk=0;k<list.Count;k++){temp=temp+list[k];}}else{List<double>temp=newList<double>();for(inti=0;i<list.Count;i++){if(list[i]>2.00){temp.Add(list[i]);}}intseed=rd.Next(0,temp.Count-1);inta=rd.Next(0,Int32.Parse(((temp[seed]-1)*100).ToString()));list.Add(a*0.01+1);list.Add(temp[seed]-(a*0.01+1));for(intj=0;j<list.Count;j++){if(list[j]==temp[seed]){list.Remove(list[j]);break;}}}getRandom();}}privatevoidbutton1_Click(objectsender,EventArgse){list.Clear();list.Add(100);this.listBox1.Items.Clear();getRandom();doubleresult=0.00;for(inti=0;i<list.Count;i++){this.listBox1.Items.Add(list[i].ToString());result=result+list[i];}this.textBox1.Text=result.ToString();}这个可以用,但是存在极端情况没处理,就是分成的份数大于50份,这个我的想法是把最小的3个相加,然后随机分成2分,进行递归,直到减到50份。
解决方案:
if(list[i]>2.00)这个改成if(list[i]>3.00)否则会有小于1的数
解决方案:
//生成double随机数publicstaticdoubleNextDouble(Randomrand,doublemindouble,doublemaxdouble){if(rand!=null){returnMath.Round(rand.NextDouble()*(maxdouble-mindouble)+mindouble,2);}else{return0.0d;}}//获取随机数组GetListincount分配数量inmoney分配总额minmoney单个最小金额maxmoney单个最大金额publicList<double>GetList(intincount,doubleinmoney,doubleminmoney,doublemaxmoney){List<double>outarray=newList<double>();if(minmoney<0.01){//单个最小金额不得小于0.01returnoutarray;}if(inmoney/incount<minmoney){//单个金额小于最低金额returnoutarray;}doublesummoney=0;//随机累加总金额Randomran=newRandom();for(inti=0;i<incount;i++){if(i+1==incount){outarray.Add(inmoney-summoney);returnoutarray;}doublenow=GetRanDouble(ran,incount,inmoney,minmoney,maxmoney,refoutarray,summoney);if(now==0){returnoutarray;}else{outarray.Add(now);summoney+=now;}}returnoutarray;}//根据当前数组分配随机数publicdoubleGetRanDouble(Randomran,intincount,doubleinmoney,doubleminmoney,doublemaxmoney,refList<double>outarray,doublesummoney){//先获取一个随机数doublenowmoney=NextDouble(ran,minmoney,maxmoney);//剩余可分配数量intsycount=incount-outarray.Count-1;//剩余可分配金额doublesymoney=inmoney-summoney-nowmoney;//当剩余平均金额小于最小金额时,说明当前分配的金额过大,就以最小单位0.01往下递归获取较小的随机数,以便保证后面的数据最少能大于最低单个金额if(symoney/sycount<minmoney){returnGetRanDouble(ran,incount,inmoney,minmoney,nowmoney-0.01,refoutarray,summoney);}//当前剩余平均金额等于最小金额时直接把当前数据加到数组上后面都按最小金额分配直接返回好了elseif(symoney/sycount==minmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(minmoney);}return0;}//当前剩余平均金额大于最小金额小于最大金额时当前随机数就没啥问题直接加上elseif(symoney/sycount>minmoney&&symoney/sycount<minmoney){returnnowmoney;}//同上剩余的钱太多直接都给最大值elseif(symoney/sycount==maxmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(maxmoney);}return0;}//懒得写了else{returnGetRanDouble(ran,incount,inmoney,nowmoney+0.01,minmoney,refoutarray,summoney);}}
PS:哥们在公司内网写的,,,突然发现不能copy到外网。。。坑爹给你在文本编辑器手敲出来的应该还有地方需要完善但是亲测可用
解决方案:
引用20楼ck7193的回复:
//生成double随机数publicstaticdoubleNextDouble(Randomrand,doublemindouble,doublemaxdouble){if(rand!=null){returnMath.Round(rand.NextDouble()*(maxdouble-mindouble)+mindouble,2);}else{return0.0d;}}//获取随机数组GetListincount分配数量inmoney分配总额minmoney单个最小金额maxmoney单个最大金额publicList<double>GetList(intincount,doubleinmoney,doubleminmoney,doublemaxmoney){List<double>outarray=newList<double>();if(minmoney<0.01){//单个最小金额不得小于0.01returnoutarray;}if(inmoney/incount<minmoney){//单个金额小于最低金额returnoutarray;}doublesummoney=0;//随机累加总金额Randomran=newRandom();for(inti=0;i<incount;i++){if(i+1==incount){outarray.Add(inmoney-summoney);returnoutarray;}doublenow=GetRanDouble(ran,incount,inmoney,minmoney,maxmoney,refoutarray,summoney);if(now==0){returnoutarray;}else{outarray.Add(now);summoney+=now;}}returnoutarray;}//根据当前数组分配随机数publicdoubleGetRanDouble(Randomran,intincount,doubleinmoney,doubleminmoney,doublemaxmoney,refList<double>outarray,doublesummoney){//先获取一个随机数doublenowmoney=NextDouble(ran,minmoney,maxmoney);//剩余可分配数量intsycount=incount-outarray.Count-1;//剩余可分配金额doublesymoney=inmoney-summoney-nowmoney;//当剩余平均金额小于最小金额时,说明当前分配的金额过大,就以最小单位0.01往下递归获取较小的随机数,以便保证后面的数据最少能大于最低单个金额if(symoney/sycount<minmoney){returnGetRanDouble(ran,incount,inmoney,minmoney,nowmoney-0.01,refoutarray,summoney);}//当前剩余平均金额等于最小金额时直接把当前数据加到数组上后面都按最小金额分配直接返回好了elseif(symoney/sycount==minmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(minmoney);}return0;}//当前剩余平均金额大于最小金额小于最大金额时当前随机数就没啥问题直接加上elseif(symoney/sycount>minmoney&&symoney/sycount<minmoney){returnnowmoney;}//同上剩余的钱太多直接都给最大值elseif(symoney/sycount==maxmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(maxmoney);}return0;}//懒得写了else{returnGetRanDouble(ran,incount,inmoney,nowmoney+0.01,minmoney,refoutarray,summoney);}}PS:哥们在公司内网写的,,,突然发现不能copy到外网。。。坑爹给你在文本编辑器手敲出来的应该还有地方需要完善但是亲测可用
测出来点问题,,,用double的话会因为精度的问题导致死循环改成int传入的时候乘100输出的时候除100就好了
解决方案:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的
解决方案:
还有一个情况,100快20个人分最高10快,最低1快会出现min值大于max这种情况
解决方案:
还有100快10个人分最高10快最低1快会出现10个人一人10这样的情况
解决方案:
引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的
单位是分,肯定是整数
解决方案:
引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
总额是10000的时候2000人分最低1最高100结果就是这样
解决方案:
引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
图片发错了不号意思总额是10000的时候2000人分最低1最高100结果就是这样
解决方案:
引用26楼hejianxiong520的回复:
Quote: 引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
总额是10000的时候2000人分最低1最高100结果就是这样
//根据当期数组获取随机数publicintGetRanDouble(Randomran,intincount,intinmoney,refintminmoney,refintmaxmoney,refList<int>outarray,intsummoney){intnowmoney=ran.Next(minmoney,maxmoney);doublesycount=incount-outarray.Count-1;doublesymoney=inmoney-summoney-nowmoney;if((symoney/sycount)<minmoney){maxmoney=nowmoney-1;returnGetRanDouble(ran,incount,inmoney,refminmoney,refmaxmoney,refoutarray,summoney);}elseif((symoney/sycount)==minmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(minmoney);}return0;}elseif((symoney/sycount)>minmoney&&(symoney/sycount)<maxmoney){returnnowmoney;}elseif((symoney/sycount)==maxmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(maxmoney);}return0;}else{minmoney=nowmoney+1;returnGetRanDouble(ran,incount,inmoney,refminmoney,refmaxmoney,refoutarray,summoney);}}//生成随机数组publicList<int>GetList(intincount,doubleinmoney,doubleminmoney,doublemaxmoney){List<int>outarray=newList<int>();if(minmoney<0.01){//returnoutarray;}if(inmoney/incount<minmoney){returnoutarray;}intsummoney=0;intnowinmoney=Convert.ToInt32(inmoney*100);intnowmaxmoney=Convert.ToInt32(maxmoney*100);intnowminmoney=Convert.ToInt32(minmoney*100);Randomran=newRandom();for(inti=0;i<incount;i++){if(i+1==incount){outarray.Add(nowinmoney-summoney);returnoutarray;}intnow=GetRanDouble(ran,incount,nowinmoney,refnowminmoney,refnowmaxmoney,refoutarray,summoney);if(now==0){returnoutarray;}else{outarray.Add(now);summoney+=now;}}returnoutarray;}
改了下
解决方案:
引用24楼hejianxiong520的回复:
还有100快10个人分最高10快最低1快会出现10个人一人10这样的情况
100块10个人分最低1块最高10那如果第一个小于10假如是7后面9个都给最大值10一共也只有97剩下3块不分了?这个随机数的分布取决于你的最高金额和最低金额的区间
解决方案:
引用27楼hejianxiong520的回复:
Quote: 引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
图片发错了不号意思总额是10000的时候2000人分最低1最高100结果就是这样
跟前面说的一样比如说20个人分800块那么平均值是40最大值和最小值合理的话应该围绕这个区间去设置比如如果最低是1最高是45的话会造成后面的值比较大如果最低35最高100那么后面的数值就会偏小
解决方案:
引用28楼ck7193的回复:
Quote: 引用26楼hejianxiong520的回复:
Quote: 引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
总额是10000的时候2000人分最低1最高100结果就是这样
//根据当期数组获取随机数publicintGetRanDouble(Randomran,intincount,intinmoney,refintminmoney,refintmaxmoney,refList<int>outarray,intsummoney){intnowmoney=ran.Next(minmoney,maxmoney);doublesycount=incount-outarray.Count-1;doublesymoney=inmoney-summoney-nowmoney;if((symoney/sycount)<minmoney){maxmoney=nowmoney-1;returnGetRanDouble(ran,incount,inmoney,refminmoney,refmaxmoney,refoutarray,summoney);}elseif((symoney/sycount)==minmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(minmoney);}return0;}elseif((symoney/sycount)>minmoney&&(symoney/sycount)<maxmoney){returnnowmoney;}elseif((symoney/sycount)==maxmoney){outarray.Add(nowmoney);intcount=incount-outarray.Count;for(inti=0;i<count;i++){outarray.Add(maxmoney);}return0;}else{minmoney=nowmoney+1;returnGetRanDouble(ran,incount,inmoney,refminmoney,refmaxmoney,refoutarray,summoney);}}//生成随机数组publicList<int>GetList(intincount,doubleinmoney,doubleminmoney,doublemaxmoney){List<int>outarray=newList<int>();if(minmoney<0.01){//returnoutarray;}if(inmoney/incount<minmoney){returnoutarray;}intsummoney=0;intnowinmoney=Convert.ToInt32(inmoney*100);intnowmaxmoney=Convert.ToInt32(maxmoney*100);intnowminmoney=Convert.ToInt32(minmoney*100);Randomran=newRandom();for(inti=0;i<incount;i++){if(i+1==incount){outarray.Add(nowinmoney-summoney);returnoutarray;}intnow=GetRanDouble(ran,incount,nowinmoney,refnowminmoney,refnowmaxmoney,refoutarray,summoney);if(now==0){returnoutarray;}else{outarray.Add(now);summoney+=now;}}returnoutarray;}
改了下
按分配数量20分配总额100minmoney单个最小金额1maxmoney单个最大金额20打印下输出结果是什么样子的
解决方案:
引用27楼hejianxiong520的回复:
Quote: 引用25楼shingoscar的回复:
Quote: 引用22楼hejianxiong520的回复:
7楼的朋友我看了下你的方法有几个疑问,第一个min值如果不是int类型而且double类型的时候就无法产生随机数,因为红包不可能只是整数,random.Next(min2,max2+1);这里无法转换成double类型的单位是分,肯定是整数
图片发错了不号意思总额是10000的时候2000人分最低1最高100结果就是这样
我想说结果满足了你提出来的需求,不是么?
解决方案:
有啥问题?
解决方案:
50个人,先每个人分1块钱,保证每个人都有粮吃然后剩下的50块,分成若个等份,比如10个等份,每份5块钱,再从这50人里随机挑10个人,每人分一份钱,当然分之前要判断他的钱是不是已经超过20,如果超过,则从50人除名
解决方案:
引用33楼ck7193的回复:
有啥问题?
引用33楼ck7193的回复:
有啥问题?
问题就是如果总金额是1000我分成1000份,那么速出的全是最高20最低0.1最后输出的全是1没有达到随机
解决方案:
引用33楼ck7193的回复:
有啥问题?
引用33楼ck7193的回复:
有啥问题?
问题就是如果总金额是1000我分成1000份,那么速出的全是最高20最低0.1最后输出的全是0.1没有达到随机
解决方案:
引用36楼hejianxiong520的回复:
Quote: 引用33楼ck7193的回复:
有啥问题?引用33楼ck7193的回复:
有啥问题?问题就是如果总金额是1000我分成1000份,那么速出的全是最高20最低0.1最后输出的全是0.1没有达到随机
哥们这个随机数是看你设置的随机的范围的你有多少钱要分给多少人这个随机数应该建立在平均值左右去设置你1000个人分1000块平均每个人1块你最高20后面的数值当然低了。。。不是没有达到随机是最大值和最小值没有合理化。。。我1000个人分1000块钱最低1块最高20既要保证每个人都有又要保证随机数在最低和最高之间那就只能每人1块阿。。