在PHP中通过权重生成随机结果？

``/** * getRandomWeightedElement() * Utility function for getting random values with weighting. * Pass in an associative array, such as array('A'=>5, 'B'=>45, 'C'=>50) * An array like this means that "A" has a 5% chance of being selected, "B" 45%, and "C" 50%. * The return value is the array key, A, B, or C in this case. Note that the values assigned * do not have to be percentages. The values are simply relative to each other. If one value * weight was 2, and the other weight of 1, the value with the weight of 2 has about a 66% * chance of being selected. Also note that weights should be integers. * * @param array \$weightedValues */ function getRandomWeightedElement(array \$weightedValues) { \$rand = mt_rand(1, (int) array_sum(\$weightedValues)); foreach (\$weightedValues as \$key => \$value) { \$rand -= \$value; if (\$rand <= 0) { return \$key; } } }` `

• 选择0..1之间的连续随机数
• 提高到一个幂，偏向它。 1是不加权的，越低越高，反之亦然
• 缩放到所需的范围并舍入为整数

` `function weightedrand(\$min, \$max, \$gamma) { \$offset= \$max-\$min+1; return floor(\$min+pow(lcg_value(), \$gamma)*\$offset); } echo(weightedrand(1, 10, 1.5));` `

1. 总和所有数字的权重。
2. 选一个小于这个值的随机数
3. 按顺序减去权重直到结果为负，如果是，则返回该数字。

1,2,3,4,4,4,4,4,4,5,5,5,5,5,6,6,7,7,8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,27,28,29,23,23,23,23,24,25,26,27,28,29,23,23,23,23,23,23,24,25,26,28,29,23,23,23,23,23,23,24,23,23,24,23,23,24,23,23,23,24,23,23,24,23,23,24,23,23,24,23,23,24,23,23,24,23,23,24,23,23,24,25,23,23,24,23,23,24,23,23,23,24,25 9，9，10，10

` `/** * weighted_random_simple() * Pick a random item based on weights. * * @param array \$values Array of elements to choose from * @param array \$weights An array of weights. Weight must be a positive number. * @return mixed Selected element. */ function weighted_random_simple(\$values, \$weights){ \$count = count(\$values); \$i = 0; \$n = 0; \$num = mt_rand(1, array_sum(\$weights)); while(\$i < \$count){ \$n += \$weights[\$i]; if(\$n >= \$num){ break; } \$i++; } return \$values[\$i]; }` `

` `/** * Return weighted probability * @param (array) prob=>item * @return key */ function weightedRand(\$stream) { \$pos = mt_rand(1,array_sum(array_keys(\$stream))); \$em = 0; foreach (\$stream as \$k => \$v) { \$em += \$k; if (\$em >= \$pos) return \$v; } } \$item['30'] = 'I have more chances than everybody :]'; \$item['10'] = 'I have good chances'; \$item['1'] = 'I\'m difficult to appear...'; for (\$i = 1; \$i <= 10; \$i++) { echo weightedRand(\$item).'<br />'; }` `

` `use function \nspl\a\pairs; use function \nspl\rnd\weightedChoice; \$weights = pairs(array( 1 => 10, 2 => 15, 3 => 15, 4 => 15, 5 => 15, 6 => 10, 7 => 5, 8 => 5, 9 => 5, 10 => 5 )); \$number = weightedChoice(\$weights);` `

` `<pre><?php // Set total number of iterations \$total = 1716; // Set array of random number \$arr = array(1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5); \$arr2 = array(0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 5); // Print out random numbers for (\$i=0; \$i<\$total; \$i++){ // Pick random array index \$rand = array_rand(\$arr); \$rand2 = array_rand(\$arr2); // Print array values print \$arr[\$rand] . "\t" . \$arr2[\$rand2] . "\r\n"; } ?></pre>` `
` `/** * @param array \$weightedValues * @return string */ function getRandomWeightedElement(array \$weightedValues) { \$array = array(); foreach (\$weightedValues as \$key => \$weight) { \$array = array_merge(array_fill(0, \$weight, \$key), \$array); } return \$array[array_rand(\$array)]; }` `

`getRandomWeightedElement(array('A'=>10, 'B'=>90));`

` `\$picker = new Brick\Random\RandomPicker();` `

` `\$picker->addElements([ 'foo' => 25, 'bar' => 50, 'baz' => 100 ]);` `

` `\$picker->addElement(\$object1, \$weight1); \$picker->addElement(\$object2, \$weight2);` `

` `\$element = \$picker->getRandomElement();` `

` `foreach (\$values as \$amount) { \$total += \$amount; } \$rand = mt_rand(0, \$total-1); foreach (\$values as \$amount) { \$currentTotal += \$amount; if (\$rand => \$currentTotal) { \$bucket++; } else { break; } } return \$bucket;` `

}

` `\$values_and_weights=array( 1=>1, 2=>1, 3=>2, 4=>2, 5=>2, 6=>1, 7=>1, 8=>1, 9=>1, 10=>1 );` `

` `\$pick=mt_rand(1,array_sum(\$values_and_weights)); \$x=0; foreach(\$values_and_weights as \$val=>\$wgt){ if((\$x+=\$wgt)>=\$pick){ echo "\$val"; break; } }` `

1. 数组大小增加
2. 随机选择的数量增加。

` `// Declare new array using array_walk one-liner: array_walk(\$values_and_weights,function(\$v,\$k)use(&\$limits_and_values,&\$x){\$limits_and_values[\$x+=\$v]=\$k;}); //Alternative declaration method - 4-liner, foreach() loop: /*\$x=0; foreach(\$values_and_weights as \$val=>\$wgt){ \$limits_and_values[\$x+=\$wgt]=\$val; }*/ var_export(\$limits_and_values);` `

` `array ( 1 => 1, 2 => 2, 4 => 3, 6 => 4, 8 => 5, 9 => 6, 10 => 7, 11 => 8, 12 => 9, 13 => 10, )` `

` `// \$x (from walk/loop) is the same as writing: end(\$limits_and_values); \$x=key(\$limits_and_values); \$pick=mt_rand(1,\$x); // pull random integer between 1 and highest limit/key while(!isset(\$limits_and_values[\$pick])){++\$pick;} // smallest possible loop to find key echo \$limits_and_values[\$pick]; // this is your random (weighted) value` `