加权随机算法的实现
程序员文章站
2022-07-12 18:30:57
...
加权随机算法,一般用于抽奖,资源调度等场景,话不多说,上代码:
专门剥出来一个基本对象(有效属性是weight,这个属性id都是是为了让看起来更清晰,具体使用的时候拿相应的对象来继承它既可套用算法);
这段各属性本来应该有对应的get、set方法、构造方法,这里边使用了一组lombok的标签,让代码看起来要简练不少,感兴趣的可以百度下,不喜欢的请自行删替;
算法实现,原理就是那个注释的大括号,随机数散列到不同比重的区间,获取相应比重的对象;
测试类,为了直观体现,把那个比重为50的给注释掉了(这里比重总和没有要求,任意),可以一下看看,效果如下:
概率权重这种东西,没有绝对,只有相对。
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author Veiking.cn * 加权算法原子对象,具体使用时继承 */ @Data @NoArgsConstructor @AllArgsConstructor public class Atom { /** * 对象标识参数 */ private String id; /** * 对象权重参数 */ private int weight; }
专门剥出来一个基本对象(有效属性是weight,这个属性id都是是为了让看起来更清晰,具体使用的时候拿相应的对象来继承它既可套用算法);
这段各属性本来应该有对应的get、set方法、构造方法,这里边使用了一组lombok的标签,让代码看起来要简练不少,感兴趣的可以百度下,不喜欢的请自行删替;
import java.util.ArrayList; import java.util.Random; /** * 加权随机算法,获取带有权值的随机元素 * 用于抽奖,资源调度等场景 * @author Veiking.cn */ public class WeightedRandom { /** * 获取加权随机对象 * @param atomList * @return Atom */ public static Atom getWeightedRandomAtom(ArrayList<Atom> atomList){ if(atomList.isEmpty()){ return null; } int weightSum = 0;//总权值 for(Atom atom : atomList){ weightSum += atom.getWeight(); } //获取总权值之间任意一随机数 int random = new Random().nextInt(weightSum); //random in [0, weightSum) //{.},{..},{...},{....}...根据权值概率区间,获得加权随机对象 for(Atom atom : atomList){ random -= atom.getWeight(); if (random < 0) { return atom; } } return null; } }
算法实现,原理就是那个注释的大括号,随机数散列到不同比重的区间,获取相应比重的对象;
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * 测试类 * @author Veiking.cn */ public class WeightedRandomTest { public static void main(String[] args) { ArrayList<Atom> atomList = new ArrayList<Atom>(); atomList.add(new Atom("0000001", 10)); atomList.add(new Atom("0000002", 20)); atomList.add(new Atom("0000003", 30)); atomList.add(new Atom("0000004", 40)); //atomList.add(new Atom("0000005", 50)); Atom atom; atom = WeightedRandom.getWeightedRandomAtom(atomList); System.out.println("单个实例:" + atom); //累积记录某种对象出现的次数 Map<String, Integer> countAtom = new HashMap<String, Integer>(); for (int i = 0; i < 100000; i++) { atom = WeightedRandom.getWeightedRandomAtom(atomList); if (countAtom.containsKey(atom.getId())) { countAtom.put(atom.getId(), countAtom.get(atom.getId()) + 1); } else { countAtom.put(atom.getId(), 1); } } System.out.println("概率统计:"); for (String id : countAtom.keySet()) { System.out.println(" " + id + " 出现了 " + countAtom.get(id) + " 次"); } } }
测试类,为了直观体现,把那个比重为50的给注释掉了(这里比重总和没有要求,任意),可以一下看看,效果如下:
单个实例:Atom(id=0000002, weight=20) 概率统计: 0000004 出现了 39898 次 0000002 出现了 20191 次 0000003 出现了 29888 次 0000001 出现了 10023 次
概率权重这种东西,没有绝对,只有相对。