2009-06-03 49 views
3

前幾天,you helped me to find out an algorithm for generating random strength values in an online game (thx especially John Rasch)調整生成隨機強度值的算法

function getRandomStrength($quality) { 
    $rand = mt_rand()/mt_getrandmax(); 
    $value = round(pow(M_E, ($rand - 1.033)/-0.45), 1); 
    return $value; 
} 

該函數生成1.1和9.9之間的值。現在我想調整這個函數,使它給出相同概率的值,但是在另一個區間內,例如, 1.5至8.0。如果您可以通過其他參數來實現這一點,那將是完美的。

如果你能幫助我,那會很好。提前致謝!

回答

5

原始碼中的值1.033和-0.45是提供比例1.1 - 9.9的幻數。如果您在以下代碼中傳遞1.1和9.9作爲參數$low$high,則應得到相同的結果。

function getRandomStrength($low, $high) { 
    // TODO: validate the input 
    $ln_low = log($low, M_E); 
    $ln_high = log($high, M_E); 
    $scale = $ln_high - $ln_low; 

    $rand = (mt_rand()/mt_getrandmax()) * $scale + $ln_low; 
    $value = round(pow(M_E, $rand), 1); 
    return $value; 
} 

你應該能夠在任何範圍內以通爲$low$high並獲得在該範圍內的對數分佈。 (我會離開有效範圍檢查給你,但0 < $low < $high應該是真實的。)

這是通過反向計算需要產生在所提供的範圍內,對數刻度線性度。例如,如果我希望我的對數尺度爲1.1 - 9.9,那麼我將這些值的自然對數取爲0.0953 - 2.2925。然後,我在這個線性範圍內生成一個隨機數,並將e提升爲隨機功率,將其轉換回日誌範圍。

+0

謝謝,這幾乎是雅各布B所做的,不是嗎?我用50,000次運行測試了兩種算法,並且Jacob B的算法有點快(0.563871860504 vs 0.468094348907)。 – caw 2009-06-04 14:14:37

+0

+1 - 優秀! – 2009-06-04 14:47:55

+0

@John Rasch:這段代碼的哪個方面比Jacob B的代碼好? – caw 2009-06-04 14:54:15

2

規模和置換中的歸一化範圍內的分佈:

D(a,b) = (D(0,1)*(b-a))+a 

爲了從原始函數d得到d(0,1)第一個(C,d),執行逆:

D(0,1) = (D(c,d)-c)/(d-c) 

在你的情況,d是原始函數(指數函數),a爲1.5,b爲8.5,c爲1.1,d是9.9

+0

對不起,我完全不明白這一點。你能解釋一下嗎?這似乎比Jacob B的方法更復雜,對吧?整個函數項是否乘以其他值(D *數)? – caw 2009-06-03 20:02:37

+0

理解這個例子的關鍵是D不是一個真正的函數,而是一個統計分佈(可以是統一的,指數的,無論什麼......)。我混用了一些術語來簡化它,但也許我錯了:-s – fortran 2009-06-04 16:51:00

3

一種方法將只是按比例的值:

function getRandomStrength($quality,$min,$max) { 
    $rand = mt_rand()/mt_getrandmax(); 
    $value = round(pow(M_E, ($rand - 1.033)/-0.45), 1); 
    $value = $value - 1.1 
    $value = $value * ((max-min)/8.8) 
    $value = $value + $min 
    return $value; 
} 
+0

謝謝。我已經調整了一下你的代碼(一些疏忽)。現在這是否正確? http://paste.bradleygill.com/index.php?paste_id=9919 – caw 2009-06-03 19:59:51