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条)

报告相同问题?

悬赏问题

  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制