【原創】給定隨機數的取值範圍(最小值、最大值),且要求屢次取得的隨機數最後的結果有一個固定的平均值

給定隨機數的取值範圍(最小值、最大值),且要求屢次取得的隨機數最後的結果有一個固定的平均值。算法

算法以下: 測試

 1 /******
 2 * author ztg 281099678 2018-12-06
 3 * @param    $min    float   範圍最小值
 4 * @param    $max    float   範圍最大值
 5 * @param    $avg    float   最後的平均數
 6 * @return float 結果隨機數
 7 */
 8 function avg_rand($min, $max, $avg) {
 9     $maxAvg = ($max + $avg) / 2; // 取得大區間的平均數
10     $minAvg = ($min + $avg) / 2; // 取得小區間的平均數
11 
12     if ($maxAvg - $avg == 0) {
13         return $max;
14     }
15     if ($avg - $minAvg == 0) {
16         return $min;
17     }
18     $multiple = ($avg - $minAvg) / ($maxAvg - $avg); //小區間的平均數與平均數的差距,是大區間與平均數的差距的多少倍?
19 
20     /*** 爲了更精確獲得隨機數,下面的取值,都*100 ***/
21     $baseArea = 1000; //區間的基礎範圍是多少(隨意設定,稍微大點更精確)?
22     $rMax = $baseArea + $multiple * $baseArea; //規劃區間範圍,在基礎範圍內加另外多餘倍數的區間
23 
24     $r = rand(0, $rMax); //區間隨機取一個值
25 
26     //打印測試
27     echo 'maxAvg:' . $maxAvg . ' -- minAvg:' . $minAvg . ' -- min:' . $min . ' -- max:' . $max . ' -- avg:' . $avg . ' -- rMax:' . $rMax . ' -- multiple:' . $multiple . ' -- r:' . $r   ;echo "\n";
28     //若是隨機值在大區間內,則爲小數額;不然爲大數額
29     if ($r > $multiple * $baseArea) {
30         $i = rand($min * 100, $avg * 100) / 100;
31     } else {
32         $i = rand($avg * 100 + 1, $max * 100 ) / 100;
33     }
34 
35     return $i;
36 }
37 
38 //測試
39 $res = $resMax = $resMin = [];
40 for ($i = 0; $i < 1000; $i ++) {
41     $min = 1;
42     $avg =  9.2;
43     $avg =  2.2;
44     // $avg =  6;
45     // $avg =  1;
46     // $avg =  11;
47     $max = 11;
48     $re = avg_rand($min, $max, $avg);
49     $res[] = $re;
50     if ($re < $avg) {
51         $resMin[] = $re;
52     } else {
53         $resMax[] = $re;
54     }
55 }
56 
57 echo "\n";
58 echo "\n";
59 echo 'avg:' . $avg . "\n\n";
60 echo 'result:'.( array_sum($res) / count($res)) . ' -- sum:' . array_sum($res) . ' -- count:' . count($res) ;
61 echo "\n";
62 echo "max -- avg:";echo ($max + $avg) / 2; echo ' -- count:'; print_r(count($resMax)); echo ' -- resultAvg:' . (array_sum($resMax) / count($resMax));
63 echo "\n";
64 echo 'min -- avg:' ; echo ($avg + $min) / 2; echo ' -- count:'; print_r(count($resMin)); echo ' -- resultAvg:' . (count($resMin) ? (array_sum($resMin) / count($resMin)) : 0);
65 echo "\nresMin:";print_r($resMin);
66 echo "\nresMax:";print_r($resMax);
67 echo "\nres:";print_r($res);
68 
69 exit;
相關文章
相關標籤/搜索