:根據機率取隨機數的php演算法

來源:互聯網
上載者:User

標籤:

無意間看回一年前(2009-2-10)在ppc和houlai、youd討論關於“根據機率取隨機數”演算法。問題是這樣的:

houlai:設隨機抽到A的機率為0.1,B的機率為0.2,C的機率為0.3,D的機率為0.4,現在求按此機率隨機抽出一個字母的演算法

當時自己剛學了機率論,所以沒有採用網上常見的“利用數組初始化,然後依據機率填充內容,再然後打亂該數組,最後再依據某個規則取數組內某個值”(事實上也會把記憶體給耗光),而改為另外一種方法:

horseluke:把1——100看成是一條線段。然後機率就是用於切割這條線條的,我們要做的其實只需要隨機產生一個數,然後看這個數對應於哪一條分線條就OK了。這樣,數組不需太大,而且還能得到同樣的效果。

舉個例子,A字母為30%機率,B字母為70%機率。那麼可以把這條0——100的線段分割為2段。
一段為0——30,為A字母;其餘的分屬B欄位
好了,程式現在隨機抽取了30這個數,那麼很明顯,結果就是A了。

|-----------|-----------------------|
0           30                     100

可是接下來寫的實現代碼,現在看來可真是亂七八糟的。後來youd提出了一個更好的演算法並寫出了php代碼,讓自己汗顏不已:

youd:開始是從1,1000這個機率範圍內篩選第一個數是否在他的出現機率範圍 之內,如果不在,則將機率空間,也就是k的值減去剛剛的那個數位機率空間,在本例當中就是減去100,也就是說第二個數是在1,900這個範圍內篩選 的。我想應該很容易理解,這樣篩選到最終,總會有一個數滿足要求(比如說前三個都不幸成為了非Luck Num,那麼k已經-100-200-300=400了,那麼最後一個數無論如何也會滿足要求的。相當於拿東西,第一個不是,第二個不是,第三個還不是, 那最後一個一定是。

這個演算法的優點是,對於沒有機率重疊的數字進行篩選,最多隻需要遍覽一次數組就足夠了。程式簡單,效率高

一年後看回此貼,真是感慨自己當初寫PHP代碼的幼稚(當然,現在其實水平也很菜)。趁著現在寫論文的休息時間,把youd的演算法用函數給封裝起來,以待以後使用。

不知道當年一起討論的人,現在如何了......

代碼如下:

<?php

function pro_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;
        }
    }
   
    return $result;
   
}



function pro_rand_unique_multi( $proArr, $num = 1 ){
    $result = array();
    if( $num > count($proArr) ){
        trigger_error(‘The stack number of Probability Array is GREATER THAN you set!‘, 256);
    }
   
    while(1){
        if($num < 1){
            break;
        }
        $curResult = pro_rand($proArr);
        $result[] = $curResult;
        //重設總機率精度,有待機率論驗證
        unset($proArr[$curResult]);
        $num -= 1;
    }
   
    return $result;
   
}

  

以上函數的測試代碼:

pro_rand:

$proArr = array(10,20,30,40);
mt_srand(time());

$distribute = array();
for($k = 1; $k <= 1000; $k++ ){

    $result = pro_rand($proArr);
    if(!isset($distribute[$result])){
        $distribute[$result] = 1;
    }else{
        $distribute[$result] += 1;
    }

}

ksort($distribute);
var_export($distribute);

pro_rand_unique_multi:

$proArr = array(10,20,30,40);
mt_srand(time());

$distribute = array();
for($k = 1; $k <= 1000; $k++ ){

    $result = pro_rand_unique_multi($proArr, 2);
    foreach($result as $key => $proKey){
        if(!isset($distribute[$proKey])){
            $distribute[$proKey] = 1;
        }else{
            $distribute[$proKey] += 1;
        }
    }

}

ksort($distribute);
var_export($distribute);

(完)


:根據機率取隨機數的php演算法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.