我自仰头向天笑,笑完我就去睡觉,哈哈哈哈……

【原创】给定随机数的取值范围(最小值、最大值),且要求多次取得的随机数最后的结果有一个固定的平均值

给定随机数的取值范围(最小值、最大值),且要求多次取得的随机数最后的结果有一个固定的平均值。

算法如下: 

 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;

 

posted @ 2018-12-06 22:07  轻轻的烟雾  阅读(975)  评论(0编辑  收藏  举报