假設有一個數組[100,400,200,300],它的意思是,總數是100+400+200+300=1000. 取到第一個數的機率是100/1000,取到第二個數的機率是400/1000......代碼以下:算法
function getResult(arr){ var leng = 0; for(var i=0; i<arr.length; i++){ leng+=arr[i] //獲取總數 } for(var i=0; i<arr.length; i++){ var random = parseInt(Math.random()*leng); //獲取 0-總數 之間的一個隨隨機整數 if(random<arr[i]){ return i //若是在當前的機率範圍內,獲得的就是當前機率 } else { leng-=arr[i] //不然減去當前的機率範圍,進入下一輪循環 } } }
下面來解釋一下這個算法,把數組抽象出來,假設爲a,b,c,d,這四個機率數,那麼,他們的總和就是 a+b+c+d. 畫成數軸:數組
從0-(a+b+c+d) 中取一個隨機數,數字落在對應的空間裏,取到的就是對應的機率.dom
第一次循環取數,有兩個可能: 函數
<a 或者 >a: spa
若是是第一種可能,那就直接是機率a/(a+b+c+d),獲得的對應結果就是a.直接返回.code
若是是第二種可能,那麼機率應該是(b+c+d)/(a+b+c+d).而後進入第二次循環,第二次取數咱們把a的機率空間減去,獲得新的數軸:blog
新的數軸以原來的a爲原點0,後面不變.這時候,總和變成 b+c+d.get
從 0-(b+c+d) 中取一個隨機數,數字落在對應的空間裏,取到的就是對應的機率.io
一樣有兩個可能: console
<b 或者 >b
若是是第一種,那麼它的機率就是 b/(b+c+d). 注意,這個機率出現的前提是第一次的結果是 >a ,因此總機率就是兩次乘積: (b+c+d)/(a+b+c+d) * b/(b+c+d) 獲得的結果是 b/(a+b+c+d),獲得的對應結果就是b.返回.
若是是第二種,那麼它的機率就是 (c+d)/(b+c+d). 一樣,和 >a 的結果同時出現,這種狀況的總機率應該是: (b+c+d)/(a+b+c+d) * (c+d)/(b+c+d) 獲得的結果是(c+d)/(a+b+c+d).而後進入第三次循環,而後第三次循環時,咱們再把b的機率空間減去............以此類推.............
這樣直到最後...總能取到一個機率值...
這個算法能夠用在抽獎上,好比有這樣一組獎品和對應的機率:
var gifts = [ { "name":"mac", "prop":1 }, { "name":"紅米", "prop":10 }, { "name":"u盤", "prop":40 }, { "name":"香皂", "prop":49 } ];
就能夠用前面的函數來進行抽獎:
var gArr = []; for(var i=0; i<gifts.length; i++){ gArr.push(gifts[i]['prop']) } console.log(gifts[getResult(gArr)]['name'])
源文件下載:http://pan.baidu.com/s/1oeOG2
非轉載,親測可行~~~