前言
現在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 1028764 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語言實現權重隨機算法完整實例的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!