java語言實現(xiàn)權(quán)重隨機算法完整實例
前言
現(xiàn)在app就是雨后春筍,嗖嗖的往外冒啊,有經(jīng)驗的、沒經(jīng)驗的、有資歷的、沒資歷的都想著創(chuàng)業(yè),創(chuàng)業(yè)的90%以上都要做一個app出來,好像成了創(chuàng)業(yè)的標配。
做了app就得推廣啊,怎么推,發(fā)券送錢是最多用的被不可少的了,現(xiàn)在好多產(chǎn)品或者運營都要求能夠隨機出優(yōu)惠券的金額,但是呢又不能過于隨機,送出去的券都是錢嗎,投資人的錢,是吧。
所以,在隨機生成的金額中就要求,小額度的幾率要大,大額度的幾率要小,比如說3元的70%,5塊的25%,10塊的5%,這個樣子的概率去生成優(yōu)惠券,這個怎么辦呢?
對于上述的問題,直接用我們的Random.next(Integer range);就不夠了。因為這個偽隨機不帶權(quán)重,3,5,10出現(xiàn)的概率都是一樣的。
實現(xiàn)思路
還是拿上述的例子,3出現(xiàn)的概率是70%,我們給他的權(quán)重賦值為70,5出現(xiàn)的概率為25%,我們給他的權(quán)重賦值為25,10出現(xiàn)的概率為5%,我們給他的權(quán)重賦值為5.
我們按照順序計算出權(quán)重的加和,把當前數(shù)字出現(xiàn)的權(quán)重加和前的值作為其權(quán)重范圍的起點值,把加和后的值作為其權(quán)重范圍的終點值。

這樣的話,我們就可以使用Random.next(100)來做隨機數(shù),然后判斷隨機數(shù)落在的范圍,然后映射到對應的優(yōu)惠券數(shù)值即可。
java實現(xiàn)
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){
//因為元素權(quán)重范圍有序遞增,所以這里可以改為二分查找
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;
/**
* 元素權(quán)重
*/
private Integer weight;
/**
* 權(quán)重對應隨機數(shù)范圍低線
*/
private Integer thresholdLow;
/**
* 權(quán)重對應隨機數(shù)范圍高線
*/
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;
}
}
}
結(jié)果:
2 102 876 4 876
二分法的實現(xiàn)
public WeightElement getElementByRandomValue(Integer rv){
if(rv < 0 || rv > getMaxRandomValue()-1){
return null;
}
//此時rv必然在0 - getMaxRandomValue()-1范圍內(nèi),
//也就是必然能夠命中某一個值
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;
}
}
下面再分享一則實例,加強對權(quán)重隨機算法的理解,一次到位!
權(quán)重隨機算法在抽獎,資源調(diào)度等系統(tǒng)中應用還是比較廣泛的,一個簡單的按照權(quán)重來隨機的實現(xiàn),權(quán)重為幾個隨機對象(分類)的命中的比例,權(quán)重設置越高命中越容易,之和可以不等于100;

簡單實現(xiàn)代碼如下:
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;
}
}
結(jié)果:

總結(jié)
以上就是本文關(guān)于java語言實現(xiàn)權(quán)重隨機算法完整實例的全部內(nèi)容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關(guān)文章
SpringBoot+VUE實現(xiàn)數(shù)據(jù)表格的實戰(zhàn)
本文將使用VUE+SpringBoot+MybatisPlus,以前后端分離的形式來實現(xiàn)數(shù)據(jù)表格在前端的渲染,具有一定的參考價值,感興趣的可以了解一下2021-08-08
SpringBoot四大神器之Auto onfiguration的使用
本文主要介紹了SpringBoot四大神器之Auto Configuration,springboot auto configuration的本質(zhì)就是自動配置spring的各種bean。感興趣的可以了解一下2021-10-10
WebDriver中實現(xiàn)對特定的Web區(qū)域截圖方法
這篇文章主要介紹了WebDriver中實現(xiàn)對特定的Web區(qū)域截圖方法,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下2015-06-06
解決MyEclipse中Maven設置jdk版本jdk1.8報錯問題
今天安裝了jdk1.8、tomcat8、和maven3.5.2,弄好后在myeclipse新建了一個maven項目,項目默認是jdk1.5,改成jdk1.8后項目報錯2018-10-10
關(guān)于@SpringBootApplication與@SpringBootTest的區(qū)別及用法
這篇文章主要介紹了關(guān)于@SpringBootApplication與@SpringBootTest的區(qū)別及用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

