其實發這篇博感覺并沒有什么用,太簡單了,會的人不屑看,不會的人自已動動腦子也想到了。但是看著自已的博客已經這么久沒更,真心疼~。粗略算下一篇只有代碼的水文,會占用OSC至少十幾KB的數據庫空間呢,但是,一想到亂彈里的然并卵,也就釋然了。
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
|
<?php /** * 概率計算類 * 可用于抽獎等 */ class Probability { /** * 概率統計數據 * thing => chance */ var $data = array (); var $chance_count = 0; function __construct( $initdata = array ()){ if (! empty ( $initdata )){ $this ->data = $initdata ; foreach ( $initdata as $d ){ $this ->chance_count += $d [ 'num' ]; } } } function addData( $name , $chance ){ $this ->data[]= array ( 'name' => $name , 'num' => $chance ); $this ->chance_count += $chance ; } function getOne(){ $index = rand(0, $this ->chance_count); foreach ( $this ->data as $d ){ $index = $index - $d [ 'num' ]; if ( $index <=0){ return $d [ 'name' ]; } } return '' ; } } /** * 使用示例 */ $pro = new Probability(); $pro ->addData( 'iphone' ,10); $pro ->addData( 'watch' ,30); $pro ->addData( '$18' ,50); $pro ->addData( 'thank you' ,10); $pro ->addData( 'super big' ,1); for ( $i =0; $i <100; $i ++){ echo $pro ->getOne(). "\n" ; } |
這是一個很經典的概率算法函數:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function get_rand( $proArr ) { $result = '' ; //概率數組的總概率精度 $proSum = array_sum ( $proArr ); //概率數組循環 foreach ( $proArr as $key => $proCur ) { $randNum = mt_rand(1, $proSum ); //抽取隨機數 if ( $randNum <= $proCur ) { $result = $key ; //得出結果 break ; } else { $proSum -= $proCur ; } } unset ( $proArr ); return $result ; } |
假設:我們有這樣一個數組:a獎概率20%,b獎概率30%,c獎概率50%
1
|
$prize_arr = array ( 'a' =>20, 'b' =>30, 'c' =>50); |
模擬函數執行過程:
總概率精度為20+30+50=100
第一次數組循環,$procur=20
假設抽取的隨機數rand(1,100),假設抽到$randNum=55
if判斷-------
如果$randNum<=20,則result=a
否則進入下一循環,總概率精度變為100-20=80
第二次數組循環,$procur=30
假設抽取的隨機數rand(1,80),假設抽到$randNum=33
if判斷---------
如果$randNum<=30,則result=b
否則進入下一循環,總概率精度變為80-30=50
第三次數組循環,$prosur=50;
假設抽取的隨機數rand(1,50),不管怎么抽,隨機數都會<或=50,
那么得出result=c;
因為樣本沒有改變,雖然可能抽取的隨機數不止一個,但是概率是不變的。
或者也可以這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
function get_rand( $arr ) { $pro_sum = array_sum ( $arr ); $rand_num =mt_rand(1, $pro_sum ); $tmp_num =0; foreach ( $arr as $k => $val ) { if ( $rand_num <= $val + $tmp_num ) { $n = $k ; break ; } else { $tmp_num += $val ; } } return $n ; } |
在給大家分享一個抽獎的概率算法
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
|
/* * 經典的概率算法, * $proArr是一個預先設置的數組, * 假設數組為:array(100,200,300,400), * 開始是從1,1000 這個概率范圍內篩選第一個數是否在他的出現概率范圍之內, * 如果不在,則將概率空間,也就是k的值減去剛剛的那個數字的概率空間, * 在本例當中就是減去100,也就是說第二個數是在1,900這個范圍內篩選的。 * 這樣 篩選到最終,總會有一個數滿足要求。 * 就相當于去一個箱子里摸東西, * 第一個不是,第二個不是,第三個還不是,那最后一個一定是。 * 這個算法簡單,而且效率非常 高, * 關鍵是這個算法已在我們以前的項目中有應用,尤其是大數據量的項目中效率非常棒。 */ function get_rand( $proArr ) { $result = '' ; //概率數組的總概率精度 $proSum = array_sum ( $proArr ); //概率數組循環 foreach ( $proArr as $key => $proCur ) { $randNum = mt_rand(1, $proSum ); if ( $randNum <= $proCur ) { $result = $key ; break ; } else { $proSum -= $proCur ; } } unset ( $proArr ); return $result ; } /* * 獎項數組 * 是一個二維數組,記錄了所有本次抽獎的獎項信息, * 其中id表示中獎等級,prize表示獎品,v表示中獎概率。 * 注意其中的v必須為整數,你可以將對應的 獎項的v設置成0,即意味著該獎項抽中的幾率是0, * 數組中v的總和(基數),基數越大越能體現概率的準確性。 * 本例中v的總和為100,那么平板電腦對應的 中獎概率就是1%, * 如果v的總和是10000,那中獎概率就是萬分之一了。 * */ $prize_arr = array ( '0' => array ( 'id' =>1, 'prize' => '平板電腦' , 'v' =>1), '1' => array ( 'id' =>2, 'prize' => '數碼相機' , 'v' =>5), '2' => array ( 'id' =>3, 'prize' => '音箱設備' , 'v' =>10), '3' => array ( 'id' =>4, 'prize' => '4G優盤' , 'v' =>12), '4' => array ( 'id' =>5, 'prize' => '10Q幣' , 'v' =>22), '5' => array ( 'id' =>6, 'prize' => '下次沒準就能中哦' , 'v' =>50), ); /* * 每次前端頁面的請求,PHP循環獎項設置數組, * 通過概率計算函數get_rand獲取抽中的獎項id。 * 將中獎獎品保存在數組$res['yes']中, * 而剩下的未中獎的信息保存在$res['no']中, * 最后輸出json個數數據給前端頁面。 */ foreach ( $prize_arr as $key => $val ) { $arr [ $val [ 'id' ]] = $val [ 'v' ]; } $rid = get_rand( $arr ); //根據概率獲取獎項id $res [ 'yes' ] = $prize_arr [ $rid -1][ 'prize' ]; //中獎項 unset( $prize_arr [ $rid -1]); //將中獎項從數組中剔除,剩下未中獎項 shuffle( $prize_arr ); //打亂數組順序 for ( $i =0; $i < count ( $prize_arr ); $i ++){ $pr [] = $prize_arr [ $i ][ 'prize' ]; } $res [ 'no' ] = $pr ; print_r( $res [ 'yes' ]); |