假設有3個人 能力的權重 分別為 A=>1,B=>2,C=>3,那么當有6個案子的時候 A分配到1個,B分配到2個,C分配到3個,這很合理,但是當案子只有5個,或者有7個的時候,怎么分配才算公平呢?而且案子也是一個一個相繼產生的,怎么動態分配才算合理呢?
我想到的是將權重大小轉換為每個案子被分配到的概率大小,並且加上“周期”結算,這樣每個案子的分配就達到了最合理,最優化。
下面直接上代碼----
1 class WeightService 2 { 3 protected $container; 4 protected $weight = 0; 5 6 public function __construct($arr) 7 { 8 if (!count($arr)){ 9 $this->container = []; 10 }else { 11 foreach ($arr as $item) { 12 $weight = $item['weight'] * 10000;//擴大權重 提高單次的精確度 我感覺是有用的=。= 覺得沒用的 可以拿掉 哈哈哈~ 13 $this->weight += $weight; 14 $array['id'] = $item['id']; 15 $array['weight'] = $weight; 16 $container[] = $array; 17 } 18 $this->container = $container; 19 } 20 } 21 22 public function getUid() 23 { 24 $random = $this->random(); 25 //初始化區間參數 26 $left = 0;//左閉區間 27 $right = 0;//右開區間 28 foreach ($this->container as $item){ 29 //區間寬度 30 $size = $item['weight']; 31 //右區間 + 區間寬度 32 $right += $size; 33 if ($random >= $left && $random < $right) { 34 return $item['id']; 35 }else{ 36 //准備下一輪的循環 左區間 + 區間寬度 37 $left += $size; 38 } 39 } 40 return 0; 41 } 42 43 protected function random() 44 { 45 //右邊是開區間 這個生成的是閉區間 所以要 -1 46 return mt_rand(0, $this->weight - 1); 47 } 48 }
附上測試數據精確度
測試數據可以看出精確度在99.95%以上。可以說是非常精確合理了。
至於剛才說到“周期”的問題,解決辦法就是加上一個類似“動態權重”的字段,每次被分配到減1,直到0為止。
當所有的賬號都是0的時候,說明一輪分配結束,動態權重的值全部重新初始化為權重的值,新一輪的分配開始。
到此,就完美的解決了權重分配的所有問題。