dongliantong3229 2015-04-26 20:10
浏览 59
已采纳

如何生成随机数以在PHP中生成非标准分布

I've searched through a number of similar questions, but unfortunately I haven't been able to find an answer to this problem. I hope someone can point me in the right direction.

I need to come up with a PHP function which will produce a random number within a set range and mean. The range, in my case, will always be 1 to 100. The mean could be anything within the range.

For example...

r = f(x)

where...

r = the resulting random number

x = the mean

...running this function in a loop should produce random values where the average of the resulting values should be very close to x. (The more times we loop the closer we get to x)

Running the function in a loop, assuming x = 10, should produce a curve similar to this:

     +
    + +
   +     +
  +             +     
+                               +

Where the curve starts at 1, peeks at 10, and ends at 100.

Unfortunately, I'm not well versed in statistics. Perhaps someone can help me word this problem correctly to find a solution?

  • 写回答

2条回答 默认 最新

  • douweiluo0600 2015-04-26 20:35
    关注

    interesting question. I'll sum it up:

    1. We need a funcion f(x)
    2. f returns an integer
    3. if we run f a million times the average of the integer is x(or very close at least)

    I am sure there are several approaches, but this uses the binomial distribution: http://en.wikipedia.org/wiki/Binomial_distribution

    Here is the code:

    function f($x){
        $min = 0;
        $max = 100;
        $curve = 1.1;
        $mean = $x;
        $precision = 5; //higher is more precise but slower
    
        $dist = array();
    
        $lastval = $precision;
        $belowsize = $mean-$min;
        $abovesize = $max-$mean;
        $belowfactor = pow(pow($curve,50),1/$belowsize);
    
        $left = 0;
        for($i = $min; $i< $mean; $i++){
            $dist[$i] = round($lastval*$belowfactor);
            $lastval = $lastval*$belowfactor;
            $left += $dist[$i];
        }
        $dist[$mean] = round($lastval*$belowfactor);
    
        $abovefactor = pow($left,1/$abovesize);
        for($i = $mean+1; $i <= $max; $i++){
            $dist[$i] = round($left-$left/$abovefactor);
            $left = $left/$abovefactor;
        }
    
        $map = array();
        foreach ($dist as $int => $quantity) {
            for ($x = 0; $x < $quantity; $x++) {
                $map[] = $int;
            }
        }
    
        shuffle($map);
        return current($map);
    }
    

    You can test it out like this(worked for me): $results = array();

    for($i = 0;$i<100;$i++){
        $results[] = f(20);
    }
    $average = array_sum($results) / count($results);
    echo $average;
    

    It gives a distribution curve that looks like this: Distribution curve

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效