java语言实现权重随机算法完整实例
程序员文章站
2023-12-13 19:31:58
前言
现在app就是雨后春笋,嗖嗖的往外冒啊,有经验的、没经验的、有资历的、没资历的都想着创业,创业的90%以上都要做一个app出来,好像成了创业的标配。
做了app就...
前言
现在app就是雨后春笋,嗖嗖的往外冒啊,有经验的、没经验的、有资历的、没资历的都想着创业,创业的90%以上都要做一个app出来,好像成了创业的标配。
做了app就得推广啊,怎么推,发券送钱是最多用的被不可少的了,现在好多产品或者运营都要求能够随机出优惠券的金额,但是呢又不能过于随机,送出去的券都是钱吗,投资人的钱,是吧。
所以,在随机生成的金额中就要求,小额度的几率要大,大额度的几率要小,比如说3元的70%,5块的25%,10块的5%,这个样子的概率去生成优惠券,这个怎么办呢?
对于上述的问题,直接用我们的random.next(integer range);就不够了。因为这个伪随机不带权重,3,5,10出现的概率都是一样的。
实现思路
还是拿上述的例子,3出现的概率是70%,我们给他的权重赋值为70,5出现的概率为25%,我们给他的权重赋值为25,10出现的概率为5%,我们给他的权重赋值为5.
我们按照顺序计算出权重的加和,把当前数字出现的权重加和前的值作为其权重范围的起点值,把加和后的值作为其权重范围的终点值。
这样的话,我们就可以使用random.next(100)来做随机数,然后判断随机数落在的范围,然后映射到对应的优惠券数值即可。
java实现
package com.nggirl.test.weight.random; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.random; public class weightrandom { public static void main(string[] args){ weightrandom wr = new weightrandom(); wr.initweight(new string[]{ "1","2","3","4" } , new integer[]{ 100,100,200,600 } ); random r = new random(); for (int i = 0; i < 10; i++){ integer rv = r.nextint(wr.getmaxrandomvalue()); system.out.println(rv); system.out.println(wr.getelementbyrandomvalue(rv).getkey() + " " + rv); } hashmap<string, integer> keycount = new hashmap<string, integer>(); keycount.put("1", 0); keycount.put("2", 0); keycount.put("3", 0); keycount.put("4", 0); for (int i = 0; i < 10000; i++){ integer rv = r.nextint(wr.getmaxrandomvalue()); string key = wr.getelementbyrandomvalue(rv).getkey(); keycount.put(key, keycount.get(key).intvalue()+1); } system.out.println(""); } private list<weightelement> weightelements; public void initweight(string[] keys, integer[] weights){ if(keys == null || weights == null || keys.length != weights.length){ return; } weightelements = new arraylist<weightelement>(); for (int i=0; i< keys.length; i++){ weightelements.add(new weightelement(keys[i], weights[i])); } rangeweightelemnts(); printrvs(); } private void rangeweightelemnts(){ if(weightelements.size() == 0){ return; } weightelement ele0 = weightelements.get(0); ele0.setthresholdlow(0); ele0.setthresholdhigh(ele0.getweight()); for (int i = 1; i < weightelements.size(); i++){ weightelement curelement = weightelements.get(i); weightelement preelement = weightelements.get(i - 1); curelement.setthresholdlow(preelement.getthresholdhigh()); curelement.setthresholdhigh(curelement.getthresholdlow() + curelement.getweight()); } } public weightelement getelementbyrandomvalue(integer rv){ //因为元素权重范围有序递增,所以这里可以改为二分查找 for (weightelement e:weightelements){ if(rv >= e.getthresholdlow() && rv < e.getthresholdhigh()){ return e; } } return null; } public integer getmaxrandomvalue(){ if(weightelements == null || weightelements.size() == 0){ return null; } return weightelements.get(weightelements.size() - 1).getthresholdhigh(); } public void printrvs(){ for (weightelement e:weightelements){ system.out.println(e.tostring()); } } static class weightelement{ /** * 元素标记 */ private string key; /** * 元素权重 */ private integer weight; /** * 权重对应随机数范围低线 */ private integer thresholdlow; /** * 权重对应随机数范围高线 */ private integer thresholdhigh; public weightelement(){ } public weightelement(integer weight){ this.key = weight.tostring(); this.weight = weight; } public weightelement(string key, integer weight){ this.key = key; this.weight = weight; } public string getkey() { return key; } public void setkey(string key) { this.key = key; } public integer getweight() { return weight; } public void setweight(integer weight) { this.weight = weight; } public integer getthresholdlow() { return thresholdlow; } public void setthresholdlow(integer thresholdlow) { this.thresholdlow = thresholdlow; } public integer getthresholdhigh() { return thresholdhigh; } public void setthresholdhigh(integer thresholdhigh) { this.thresholdhigh = thresholdhigh; } public string tostring(){ return "key:"+this.key + " weight:" + this.weight + " low:"+this.thresholdlow+" heigh:"+this.thresholdhigh; } } }
结果:
2 102 876 4 876
二分法的实现
public weightelement getelementbyrandomvalue(integer rv){ if(rv < 0 || rv > getmaxrandomvalue()-1){ return null; } //此时rv必然在0 - getmaxrandomvalue()-1范围内, //也就是必然能够命中某一个值 int start = 0, end = weightelements.size() - 1; int index = weightelements.size()/2; while(true){ if(rv < weightelements.get(index).getthresholdlow()){ end = index - 1; } else if(rv >= weightelements.get(index).getthresholdhigh()){ start = index + 1; } else{ return weightelements.get(index); } index = (start + end)/2; } }
下面再分享一则实例,加强对权重随机算法的理解,一次到位!
权重随机算法在抽奖,资源调度等系统中应用还是比较广泛的,一个简单的按照权重来随机的实现,权重为几个随机对象(分类)的命中的比例,权重设置越高命中越容易,之和可以不等于100;
简单实现代码如下:
import java.util.arraylist; import java.util.list; import java.util.random; public class weightrandom { static list<weightcategory> categorys = new arraylist<weightcategory>(); private static random random = new random(); public static void initdata() { weightcategory wc1 = new weightcategory("a",60); weightcategory wc2 = new weightcategory("b",20); weightcategory wc3 = new weightcategory("c",20); categorys.add(wc1); categorys.add(wc2); categorys.add(wc3); } public static void main(string[] args) { initdata(); integer weightsum = 0; for (weightcategory wc : categorys) { weightsum += wc.getweight(); } if (weightsum <= 0) { system.err.println("error: weightsum=" + weightsum.tostring()); return; } integer n = random.nextint(weightsum); // n in [0, weightsum) integer m = 0; for (weightcategory wc : categorys) { if (m <= n && n < m + wc.getweight()) { system.out.println("this random category is "+wc.getcategory()); break; } m += wc.getweight(); } } } class weightcategory { private string category; private integer weight; public weightcategory() { super(); } public weightcategory(string category, integer weight) { super(); this.setcategory(category); this.setweight(weight); } public integer getweight() { return weight; } public void setweight(integer weight) { this.weight = weight; } public string getcategory() { return category; } public void setcategory(string category) { this.category = category; } }
结果:
总结
以上就是本文关于java语言实现权重随机算法完整实例的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!