前言
現在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實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
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; } } } |
結果:
1
2
3
|
2 102 876 4 876 |
二分法的實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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;
簡單實現代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
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語言實現權重隨機算法完整實例的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
原文鏈接:http://blog.csdn.net/BuquTianya/article/details/51051672