分布式概率随机数生成器我想根据分布式概率生成一个数。比如就说每个数字有以下几种情况:Number|计数1|1502|403|154|3总计(150+40+15+3)=208那么1的概率是150/208=0.72而2的概率是40/208=0.192我怎样才能创建一个返回的随机数生成器这个概率分布的数字?我很高兴暂时将它基于静态硬编码集,但最终我希望它从数据库查询中导出概率分布。我见过这样的例子,但它们不是很通用。有什么建议么?一般方法是将随机数从区间0..1中的均匀分布提供给所需分布的累积分布函数的倒数。因此,在您的情况下,只需从0..1中抽取一个随机数x(例如使用Random.NextDouble())并根据其值返回它Thisquestionexplainsvariouswaysofgeneratingrandomnumberswithdifferentprobabilities。根据这篇文章,显示在这个问题上,最好的方法(就时间复杂度而言)是MichaelVose所说的“别名方法”。为了方便起见,我编写并提供了一个现成别名方法的随机生成器的C#实现:publicclassLoadedDie{//初始化一个新的加载的die。Probs//是一个数字数组,表示每个选择相对于所有//其他选择的相对概率。例如,如果概率是[3,4,2],那么//机会是3/9、4/9和2/9,因为概率加起来是9。publicLoadedDie(intprobs){this.prob=新列表();this.alias=newList();this.total=0;this.n=概率;这个.even=true;}随机random=newRandom();列出概率;列出别名;长总;诠释n;布尔偶数;publicLoadedDie(IEnumerableprobs){//如果为nil则引发错误if(probs==null)thrownewArgumentNullException("probs");this.prob=新列表();this.alias=newList();this.total=0;这个.even=false;变种小=新列表();变种大=新列表();vartmpprobs=新列表();foreach(varpinprobs){tmpprobs.Add(p);}this.n=tmpprobs.Count;//获取最大和最小选择并计算总多头mx=-1,mn=-1;foreach(tmpprobs中的varp){if(p<0)thrownewArgumentException("probs包含负概率。");mx=(mx<0||p>mx)?p:MX;mn=(mn<0||p0&&large.Count>0){varl=small[small.Count-1];small.RemoveAt(small.Count-1);varg=large[large.Count-1];large.RemoveAt(large.Count-1);this.prob[l]=tmpprobs[l];this.alias[l]=g;varnewprob=(tmpprobs[g]+tmpprobs[l])-this.total;tmpprobs[g]=新概率;if(newprobExample:varloadedDie=newLoadedDie(newint[]{150,40,15,3});//每个数字的概率列表://0是150,1是40,依此类推intnumber=loadedDie.nextValue();//根据给定的概率返回一个0-3之间的数字;//如果需要,该数字可以是另一个数组的索引我把这段代码放在公共领域这只做一次:每时间做:运行时间将与给定pdf数组大小的对数成正比。这很好。但是,如果你的数组大小总是这么小(在你的例子中是4),那么做一个会更有效线性搜索简单,性能也会更好。我知道这是一个老帖子,但我也搜索过这样的生成器,并且对找到的解决方案不满意。所以我写下我的想法并想与大家分享世界。在调用“NextItem(…)”之前,只需要调用“添加(…)”一段时///一个将以指定的可能性返回给定项目之一的类。///要返回的类型。///如果生成器只有一个项目,它将始终返回该项目。///如果有两个项目的可能性为0.4和0.6(您也可以使用4和6或2和3)///它将返回第一个项目10次中的4次,第二个项目10次中的6次.publicclassRandomNumberGenerator{privateList>_items=newList>();私有随机_random=newRandom();//////所有项目的可能性总和。///privatedouble_totalPossibility=0;//////添加要返回的新项目。//////返回此项目的可能性。相对于传入的其他可能性。///要返回的项目。publicvoidAdd(doublepossibility,Titem){_items.Add(newTuple(possibility,item));_totalPossibility+=可能性;}//////从具有规范的列表中随机返回一个项目确定的相对可能性。//////如果没有要返回的项目。publicTNextItem(){varrand=_random.NextDouble()*_totalPossibility;双倍值=0;foreach(varitemin_items){value+=item.Item1;if(rand感谢您提供的所有解决方案!非常感谢!@Menjaraz我尝试实施您的解决方案,因为它看起来非常资源友好,但语法有点困难所以现在,我只使用LINQSelectMany()和Enumerable.Repeat()将我的摘要转换为一个平面值列表。publicclassInventoryItemQuantityRandomGenerator{privatereadonlyRandom_random;privatereadonlyIQueryable_quantities;publicInventoryItemQuantityRandomGenerator(IRepositorydatabase,intmax){_quantitieser=database.Where(x=>x.Quantityx.Quantity).Select(x=>new{Quantity=x.Key,Count=x.Count()}).SelectMany(x=>Enumerable.Repeat(x.Quantity,x.Count));_random=newRandom();}publicintNext(){return_quantities.ElementAt(_random.Next(0,_quantities.Count()-1));}}用我的方法,简单易懂。我不计算0...1范围内的部分,我只是使用“ProbabilitypPool”(听起来很酷,不是吗?)在圆图中,您可以看到池中每个元素的权重Here你可以看到轮盘赌累积概率的实现`//一些类或结构,用于表示要轮盘的项目publicclassItem{publicstringname;//不仅是字符串,任何类型的数据publicint机会;//获得该物品的几率}publicclassProportionalWheelSelection{publicstaticRandomrnd=newRandom();//从任何地方使用的静态方法。您可以使其重载不仅接受列表,还接受数组://publicstaticItemSelectItem(Item[]items)...publicstaticItemSelectItem(Listitems){//计算所有部分的总和。intpoolSize=0;对于(inti=0;iitems=newList();items.Add(newItem(){name="Anna",chance=100});items.Add(newItem(){name="Alex",chance=125});items.Add(newItem(){name="Dog",chance=50});items.Add(newItem(){name="Cat",chance=35});ItemnewItem=ProportionalWheelSelection.SelectItem(项目);这是使用反分配函数的实际情况:usingSystem;使用System.Linq;//...privatestaticreadonlyRandomRandomGenerator=newRandom();privateintGetDistributedRandomNumber(){doubletotalCount=208;varnumber1Prob=150/totalCount;varnumber2Prob=(150+40)/totalCount;varnumber3Prob=(150+40+15)/totalCount;varrandomNumber=RandomGenerator.NextDouble();intselectedNumber;if(randomNumber=number1Prob&&randomNumber=number2Prob&&randomNumbervalidation随机分配的示例:inttotalNumber1Count=0;inttotalNumber2Count=0;inttotalNumber3Count=0;inttotalNumber4Count=0;inttestTotalCount=100;foreach(varunusedinEnumerable.Range(1,testTotalCount)){intselectedNumber=GetDistributedRandomNumber();Console.WriteLine($"selectednumberis{selectedNumber}");if(selectedNumber==1){totalNumber1Count+=1;}if(selectedNumber==2){totalNumber2Count+=1;}if(selectedNumber==3){totalNumber3Count+=1;}if(selectedNumber==4){totalNumber4Count+=1;}}Console.WriteLine("");Console.WriteLine($"number1->选择的总数是{totalNumber1Count}({100*(totalNumber1Count/(double)testTotalCount):0.0}%");Console.WriteLine($"number2->选择的总数是{totalNumber2Count}({100*(totalNumber2Count/(double)testTotalCount):0.0}%");Console.WriteLine($"number3->选择的总数为{totalNumber3Count}({100*(totalNumber3Count/(double)testTotalCount):0.0}%");Console.WriteLine($"number4->选择的总数是{totalNumber4Count}({100*(totalNumber4Count/(double)testTotalCount):0.0}%");输出示例:以上就是C#学习教程:分布式概率随机数生成器分享的全部内容,如果对大家有用还有需要了解更多C#学习教程的,希望大家多多关注---所选号码为1所选号码为1所选号码为1所选号码为1所选号码为2所选号码为1...所选号码为2所选号码为3所选号码为1所选号码为1所选号码为1所选数字为1所选数字为1数字1->所选总计数为71(71.0%)数字2->所选总计数为20(20.0%)数字3->所选总计数为8(8.0%)数字4->总选数为1(1.0%)本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
