php取随机数概率算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php取随机数概率算法相关的知识,希望对你有一定的参考价值。

从1到200按一定概率取数,保留两位小数

1-10为60%;
10-50为25%
50-100为10%
100-200为5%
求大神解决问题

参考技术A

问题有点模糊,我先暂时把“保留两位小数”理解成“[输出的随机数]保留两位小数”,而非其他因素保留多少小数。
又把“1-10”,理解成包括1和10在内其两数之间的小数,
把10-50,理解成10.01到50.00之间的数,不包括10.00。以此类推。

<?php
function genRandom()
$p=rand(1,100);
if($p<=60) $r=rand(100,1000);
elseif($p>60 and $p<=85) $r=rand(1001,5000);
elseif($p>85 and $p<=95) $r=rand(5001,10000);
else $r=rand(10001, 20000);
return $r/100;

$a=array();
$total=50000;
for($i=0;$i<$total;$i++)
$c=genRandom();
if($c>=1 and $c<=10) $p=0;
elseif($c>10 and $c<=50) $p=1;
elseif($c>50 and $c<=100) $p=2;
elseif($c>100 and $c<=200) $p=3;
else $p=4;
if(!array_key_exists($p, $a)) $a[$p]=1;
else $a[$p]++;

if(!array_key_exists(4, $a)) $a[4]=0;
echo "总样本数".$total.'<br/>';
echo "1-10样本数".$a[0].', 占'.($a[0]/$total*100).'%<br/>';
echo ">10-50样本数".$a[1].', 占'.($a[1]/$total*100).'%<br/>';
echo ">50-100样本数".$a[2].', 占'.($a[2]/$total*100).'%<br/>';
echo ">100-200样本数".$a[3].', 占'.($a[3]/$total*100).'%<br/>';
echo "其他样本数".$a[4].', 占'.($a[4]/$total*100).'%<br/>';

总样本数50000
1-10样本数30052, 占60.104%
>10-50样本数12404, 占24.808%
>50-100样本数4993, 占9.986%
>100-200样本数2551, 占5.102%
其他样本数0, 占0%

参考技术B $Probability["1-10"] = 0.6;
$Probability["11-50"] = 0.25;
$Probability["51-100"] = 0.10;
$Probability["101-200"] = 0.05;
//扩大1000倍便于计算
foreach($Probability as $k => $v)
   $Probability[$k] = $v*1000;


$Num = 0;
$Random = rand(1,1000);//生成随机数
foreach($Probability as $k => $v)
   if(  $Num < $Random && $Random <= $v+$Num)
      //进入这里表示随机数在哪一个范围内
      $Range = explode("-", $k);
      //生成范围区间的随机数
      $Result = rand($Range[0],$Range[1]);
      echo $Result;
      break;
   else
      $Num += $v;
   



希望对您有帮助

追问

谢谢大神的回答,可是需要保留两位小数,1.00-10.00,之间的小数也要算

追答

结果这行改成 

$Result =  rand($Range[0]*100,$Range[1]*100)/100;

我测试过是可以运行的

参考技术C <?php
function get_rand($proArr)
$result = '';

//概率数组的总概率精度
$proSum = array_sum($proArr);

//概率数组循环
foreach ($proArr as $key => $proCur)
$randNum = mt_rand(1, $proSum);
if ($randNum <= $proCur)
$result = $key;
break;
else
$proSum -= $proCur;


unset ($proArr);

return $result;


$prize_arr = array(
'0' => array('id'=>1,'prize'=>'100-200','v'=>5),
'1' => array('id'=>2,'prize'=>'50-100','v'=>10),
'2' => array('id'=>3,'prize'=>'10-50','v'=>25),
'3' => array('id'=>4,'prize'=>'1-10','v'=>60),
);
foreach ($prize_arr as $key => $val)
$arr[$val['id']] = $val['v'];

$rid = get_rand($arr); //根据概率获取奖项id
$res['yes'] = $prize_arr[$rid-1]['prize']; //中奖项
unset($prize_arr[$rid-1]); //将中奖项从数组中剔除,剩下未中奖项
shuffle($prize_arr); //打乱数组顺序
for($i=0;$i<count($prize_arr);$i++)
$pr[] = $prize_arr[$i]['prize'];

$res['no'] = $pr;
$num = $res['yes'];
$str_num = explode('-',$num);
$row = rand($str_num[0],$str_num[1]);
//$row最终结果几率如数组V可调整
echo $row;

?>追问

必须要有两位小数

追答

function get_rand($proArr)
$result = '';

//概率数组的总概率精度
$proSum = array_sum($proArr);

//概率数组循环
foreach ($proArr as $key => $proCur)
$randNum = mt_rand(1, $proSum);
if ($randNum array('id'=>1,'prize'=>'10000-20000','v'=>5),
'1' => array('id'=>2,'prize'=>'5000-10000','v'=>10),
'2' => array('id'=>3,'prize'=>'1000-5000','v'=>25),
'3' => array('id'=>4,'prize'=>'100-1000','v'=>60),
);

foreach ($prize_arr as $key => $val)
$arr[$val['id']] = $val['v'];


$rid = get_rand($arr); //根据概率获取奖项id

$res['yes'] = $prize_arr[$rid-1]['prize']; //中奖项
unset($prize_arr[$rid-1]); //将中奖项从数组中剔除,剩下未中奖项
shuffle($prize_arr); //打乱数组顺序
for($i=0;$i<count($prize_arr);$i++)
$pr[] = $prize_arr[$i]['prize'];

$res['no'] = $pr;
$num = $res['yes'];
$str_num = explode('-',$num);
$row = rand($str_num[0],$str_num[1]);
$str = (intval($row)/100);
echo $str;
就这样

参考技术D $number = array(
    1 => array('n' => mt_rand(1, 10), 'p' => 60),
    2 => array('n' => mt_rand(10, 50), 'p' => 25),
    3 => array('n' => mt_rand(50, 100), 'p' => 10),
    4 => array('n' => mt_rand(100, 200), 'p' => 5),
);

function rand_number($numbers)

    $sum = 100;
    foreach ($numbers as $key => $number) 
        $rand = mt_rand(1, $sum);
        if ($rand <= $number['p']) 
            $result = $key;
            break;
         else 
            $sum = $sum - $number['p'];
        
    
    return $result;


echo $number[rand_number($number)]['n'];

追问

不能运行

追答$number = array(
    1 => array('n' => mt_rand(1 * 100, 10 * 100) / 100, 'p' => 60),
    2 => array('n' => mt_rand(10 * 100, 50 * 100) / 100, 'p' => 25),
    3 => array('n' => mt_rand(50 * 100, 100 * 100) / 100, 'p' => 10),
    4 => array('n' => mt_rand(100 * 100, 200 * 100) / 100, 'p' => 5),
);

function rand_number($numbers)

    $sum = 100;
    foreach ($numbers as $key => $number) 
        $rand = mt_rand(1, $sum);
        if ($rand <= $number['p']) 
            $result = $key;
            break;
         else 
            $sum = $sum - $number['p'];
        
    
    return $result;


echo $number[rand_number($number)]['n'];    //输出具体数字

我测试时可以运行的.

php概率算法(转)

这是一个很经典的概率算法函数:

function get_rand($proArr) { 
    $result = ‘‘; 
    //概率数组的总概率精度 
    $proSum = array_sum($proArr); 
    //概率数组循环 
    foreach ($proArr as $key => $proCur) { 
        $randNum = mt_rand(1, $proSum);             //抽取随机数
        if ($randNum <= $proCur) { 
            $result = $key;                         //得出结果
            break; 
        } else { 
            $proSum -= $proCur;                     
        } 
    } 
    unset ($proArr); 
    return $result; 
}

假设:我们有这样一个数组:a奖概率20%,b奖概率30%,c奖概率50%

$prize_arr =array(a=>20,b=>30,c=>50);

模拟函数执行过程:

总概率精度为20+30+50=100

第一次数组循环,$procur=20

假设抽取的随机数rand(1,100),假设抽到$randNum=55

if判断-------

如果$randNum<=20,则result=a

否则进入下一循环,总概率精度变为100-20=80

 


第二次数组循环,$procur=30

假设抽取的随机数rand(1,80),假设抽到$randNum=33

if判断---------

如果$randNum<=30,则result=b

否则进入下一循环,总概率精度变为80-30=50


第三次数组循环,$prosur=50;

假设抽取的随机数rand(1,50),不管怎么抽,随机数都会<或=50,

那么得出result=c;

 因为样本没有改变,虽然可能抽取的随机数不止一个,但是概率是不变的。

 

 

或者也可以这样:

function get_rand($arr)
    {
        $pro_sum=array_sum($arr);
        $rand_num=mt_rand(1,$pro_sum);
        $tmp_num=0;
        foreach($arr as $k=>$val)
        {    
            if($rand_num<=$val+$tmp_num)
            {
                $n=$k;
                break;
            }else
            {
                $tmp_num+=$val;
            }
        }
        return $n;
    }

 

以上是关于php取随机数概率算法的主要内容,如果未能解决你的问题,请参考以下文章

php概率算法(转)

STL系列十一 随机三趣题——随机重排,文件中随机取一行,生成N个随机数

Codeforces 1114E(数学+随机算法)

js 随机按机率取数

洗牌算法

概率图模型(推理:消息传递算法)