加权随机数

class WeightElement {

  private $_item;
  private $_weight;
  private $min;
  private $max;
  public function __construct($item, $weight){
    $this->_item = $item;
    $this->_weight = $weight;
  }

  public function setMin($min){
    $this->min = $min;
  }

  public function setMax($max){
    $this->max = $max;
  }

  public function getMin(){
    return $this->min;
  }

  public function getMax(){
    return $this->max;
  }

  public function getItem(){
    return $this->_item;
  }
}


class WeightRandom {
  private $items = array();
  function __construct()
  {
    # code...
  }

  public function addItem($item, $weight = 1){
    $this->items[$item] = $weight;
  }

  public function getItem(){
    if (empty($this->items)) {
      return '';
    }
    $min = 0;
    $max = 0;
    $elements = array();
    foreach ($this->items as $key => $value) {
      $max = $min + $value;
      $element = new WeightElement($key, $value);
      $element->setMin($min);
      $element->setMax($max);
      $elements[] = $element;
      $min = $max;
    }

    $rv = rand(0, array_sum($this->items)-1);
    return $this->getElementByRandomValue($elements, $rv);
  }

  protected function getElementByRandomValue($elements, $rv){
    $start = 0;
    $end = count($elements) - 1;
    $index = (int)(count($elements) / 2);
    while (true) {
      $element = $elements[$index];
      if ($rv < $element->getMin()) {
        $end = $index - 1;
      } elseif($rv >= $element->getMax()){
        $start = $index + 1;
      } else {
        return $element->getItem();
      }
      $index = (int)(($start + $end) / 2);
    }
  }
}

$random = new WeightRandom();
$random->addItem('li', 5);
$random->addItem('wang', 4);
$random->addItem('zhao', 3);
$random->addItem('sun', 2);
$random->addItem('qian', 1);
$array = array();
for ($i=0; $i < 1500; $i++) {
  $item = $random->getItem();
  $array[$item] = isset($array[$item]) ? $array[$item] + 1 : 1;
}
arsort($array);
error_log(var_export($array,true));

结果:

[22-May-2018 15:14:13 Etc/GMT-8] array (
  'li' => 501,
  'wang' => 400,
  'zhao' => 295,
  'sun' => 201,
  'qian' => 103,
)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值