在PHP中按权重生成随机结果?

kyc*_*yct 55 php random

我知道如何在PHP中生成一个随机数,但是我想要一个介于1-10之间的随机数,但我想要更多的3,4,5,然后是8,9,10.这怎么可能?我会发布我尝试的但老实说,我甚至不知道从哪里开始.

Bra*_*rad 93

根据@ Allain的回答/链接,我用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;
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • `$ weightedValues`是否必须按升序排列才能生效? (4认同)
  • @chiborg我有同样的初始直觉,但事实证明,数组不必全部排序.我通过调整加权数组来验证它,通过多次调用函数并验证统计匹配的数字.无论订单如何,他们都会这样做; 结果是一致的.但是,顺序会极大地影响执行速度:最大权重首先产生最大速度,而最低权重首先产生最差性能. (4认同)

bob*_*nce 29

对于一个有效的随机数,一致地向着标度的一端倾斜:

  • 选择介于0..1之间的连续随机数
  • 提高功率γ,使其偏置.1表示未加权,下限表示更高的数字,反之亦然
  • 缩放到所需范围并舍入为整数

例如.在PHP(未经测试):

function weightedrand($min, $max, $gamma) {
    $offset= $max-$min+1;
    return floor($min+pow(lcg_value(), $gamma)*$offset);
}
echo(weightedrand(1, 10, 1.5));
Run Code Online (Sandbox Code Playgroud)

  • @Optimus:它是一个加权因子:函数的输出是它对伽马幂的输入,其中输入在0和1之间.因此,例如对于gamma = 0.5,你得到一个平方根曲线,它从0向上弯曲比直线快,所以你得到更高的数字.有关伽马曲线的信息,请参阅[wiki](http://en.wikipedia.org/wiki/Gamma_correction)(传统上用于图像校正目的) (2认同)

All*_*nde 23

有一个很好的教程给你.

基本上:

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


Iai*_*der 11

对此的天真黑客将是建立一个列表或数组

1,2,3,3,3,3,4,4,4,4,4,5,5,5,5,5,5,6,6,7,7,7,8,8, 9,9,10,10

然后从中随机选择.

  • 唯一的缺点是,如果你想要数字1比其他数字1万亿倍,你需要一个1万亿+元素的数组. (10认同)

Bra*_*rks 6

本教程将以PHP的形式引导您完成多个剪切和粘贴解决方案.请注意,由于下面的注释,此例程会稍微修改一下您在该页面上的内容.

从帖子中获取的功能:

/**
 * 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]; 
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*říž 5

/**
 * @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)];
}
Run Code Online (Sandbox Code Playgroud)

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

这是非常简单的方法。如何获得随机加权元素。我填充数组变量 $key。我得到 $key 数组 $weight x。之后,使用 array_rand 进行排列。我有随机值;)。