从任意加权列表生成随机数

时间:2014-05-27 21:19:08

标签: javascript php statistics

这就是我需要做的事情,我将在PHP和JavaScript中做到这一点。

我有一个数字列表,范围从1到300-500(我还没有设置限制)。我将运行一个绘图,其中将从给定范围随机选取10个数字。

这里有一个棘手的部分:我希望不太可能制定一些数字。这些300-500的一小部分将被标记为"幸运数字"。

例如,在100幅图纸中,大多数数字具有相同的绘制机会,除少数之外,每30-50幅图纸只会被挑选一次。

基本上我需要人为地设定某些数字的概率,同时保持与其余数字的均匀分布。

到目前为止,我发现的唯一类似事情就是这个问题:Generate A Weighted Random Number,问题是我的规格有更多的数字(最多500个)所以权重会变得非常小而且据说这个可能是该解决方案的问题(拒绝采样)。不过,我还在尝试,但我想知道是否有其他解决方案。

数学不是我的事,所以我很欣赏任何输入。感谢。

2 个答案:

答案 0 :(得分:1)

我写了一个快速的小JSFiddle来处理这个问题:

http://jsfiddle.net/cHVsC/

基本上,我生成一个名为pool的数组,其中包含完整的数字列表,包括重量加权数字的重复数据。然后选择与非加权数组完全相同。

示例JS:

function generatePool (count, luckyNumbers) {
    var arr = [], i, j;
    for (i = 1; i <= count; i++) {
        if (luckyNumbers[i]) {
            for (j = 0; j < luckyNumbers[i]; j++) {
                arr.push(i);
            }
        } else {
            arr.push(i);
        }
    }
    return arr;
}

function randomNumber (pool) {
    return pool[ Math.floor(Math.random() * pool.length) ];
}

一个用法示例

var luckyNumbers = {};
luckyNumbers[13] = 10;
luckyNumbers[25] = 100;

var pool = generatePool(300, luckyNumbers);

alert(randomNumber(pool));

更新:我误解了最初的目标。这是一个更新版本:

function generatePool (count, luckyNumbers) {
    var arr = [], i, j;
    for (i = 1; i <= count; i++) {
        for (j = 0; j < (luckyNumbers[i] || 10); j++) {
            arr.push(i);
        }
    }
    return arr;
}

function randomNumber (pool) {
    return pool[ Math.floor(Math.random() * pool.length) ];
}

用法示例:

var luckyNumbers = {};
luckyNumbers[13] = 1; //-- ~1:10 odds
luckyNumbers[25] = 2; //-- ~2:10 odds

var pool = generatePool(300, luckyNumbers);

console.log(randomNumber(pool));

答案 1 :(得分:1)

function pick_number() {

    $lucky_numbers = range(1,10);
    $regular_numbers = range(11,100);

    //pick lucky numbers with 30% probability
    //even though they only represent 10% of all numbers
    if(rand(1,100) <= 30) {
        $index = rand(0,count($lucky_numbers)-1);
        $number = $lucky_numbers[$index];
    }
    else {
        $index = rand(0,count($regular_numbers)-1);
        $number = $regular_numbers[$index];
    }

    return $number;
}

$frequency = [];

foreach(range(1,1000) as $i) {
    $frequency[pick_number()]++;
}

ksort($frequency);

print_r($frequency);

<强>输出

Array
(
    [1] => 27
    [2] => 31
    [3] => 31
    [4] => 37
    [5] => 25
    [6] => 37
    [7] => 33
    [8] => 20
    [9] => 34
    [10] => 33
    [11] => 7
    [12] => 11
    [13] => 11
    [14] => 9
    [15] => 13
    [16] => 9
    [17] => 13
    [18] => 5
    [19] => 4
    [20] => 6
    [21] => 9
    [22] => 3
    [23] => 4
    [24] => 9
    [25] => 6
    [26] => 10
    [27] => 2
    [28] => 10
    [29] => 14
    [30] => 7
    [31] => 7
    [32] => 3
    [33] => 13
    [34] => 8
    [35] => 14
    [36] => 8
    [37] => 8
    [38] => 3
    [39] => 13
    [40] => 12
    [41] => 7
    [42] => 7
    [43] => 8
    [44] => 4
    [45] => 8
    [46] => 10
    [47] => 7
    [48] => 5
    [49] => 5
    [50] => 6
    [51] => 9
    [52] => 7
    [53] => 14
    [54] => 12
    [55] => 4
    [56] => 9
    [57] => 4
    [58] => 8
    [59] => 1
    [60] => 9
    [61] => 14
    [62] => 8
    [63] => 13
    [64] => 4
    [65] => 4
    [66] => 10
    [67] => 11
    [68] => 7
    [69] => 7
    [70] => 8
    [71] => 4
    [72] => 4
    [73] => 6
    [74] => 6
    [75] => 10
    [76] => 6
    [77] => 10
    [78] => 4
    [79] => 10
    [80] => 9
    [81] => 5
    [82] => 8
    [83] => 7
    [84] => 8
    [85] => 8
    [86] => 6
    [87] => 10
    [88] => 8
    [89] => 5
    [90] => 6
    [91] => 8
    [92] => 2
    [93] => 8
    [94] => 4
    [95] => 8
    [96] => 5
    [97] => 6
    [98] => 12
    [99] => 11
    [100] => 7
)