【问题标题】:PHP Split int into random valuesPHP将int拆分为随机值
【发布时间】:2019-01-05 14:45:45
【问题描述】:

我有一个名为 v_cnt 的 int,它使用投票系统的最大值,他们使用 mt_rand 生成随机数的“投票”(用于游戏目的而不是操纵系统)

// vote 1
$vote_limit = $v_cnt;
$vote_1 = mt_rand(0, $vote_limit); 
// vote 2
$vote_limit = $v_cnt - $vote_1; if($vote_limit < 0){ $vote_limit = 0;}
$vote_2 = mt_rand(0, $vote_limit);
// vote 3
$vote_limit = $v_cnt - ($vote_1 + $vote_2); if($vote_limit < 0){ $vote_limit = 0;}
$vote_3 = mt_rand(0, $vote_limit);

这给了我 vote_1、vote_2 和 vote_3 这是理想的。但是,由于 mt_rand 是一个达到极限的随机值,我没有得到我需要的结果,因为我需要它来计算这样的结果;

(vote_1 + vote_2 + vote_3) = $v_cnt

所以本质上我需要将一个 int 拆分为 3 个随机值,这些值的总和必须等于起始数字。我希望这是有道理的。

谢谢。

【问题讨论】:

    标签: php random int


    【解决方案1】:

    你不能同时拥有所有三个。这是不可能的。
    前两个,当然。但最后一个只能是一个数字,这就是剩下的。

    // vote 1
    $vote_limit = $v_cnt;
    $vote_1 = mt_rand(0, $vote_limit); 
    // vote 2
    $vote_limit = $v_cnt - $vote_1; 
    $vote_2 = mt_rand(0, $vote_limit);
    // vote 3
    $vote_3 = $v_cnt - ($vote_1 + $vote_2); 
    

    https://3v4l.org/2C2bu

    我也不确定你希望这条线做什么:if($vote_limit &lt; 0){ $vote_limit = 0;}
    $vote_limit 不能为负数,因为您有随机数的限制。


    我看到您已经添加了一个拥有唯一号码的请求。
    我创建了一个新代码,它输出的 $n_votes 投票都是唯一的,没有一个是负数,并且都在 0 和 $v_cnt 之间。
    $v_cnt = 100;
    $n_votes = 3;
    
    $numbers = range(0,$v_cnt); // create array of 0->100
    shuffle($numbers); // shuffle the array
    $votes = array_fill(0, $n_votes-1, 1); // create an array that will NOT exit loop below.
    // Array_fill returns [1,1,1] which does not match the requirements so the loop starts
    
    //Loop until all values in votes are unique and none is negative
    while(count(array_unique($votes)) != $n_votes || $votes[$n_votes-1]<1){
        // Take two consecutive numbers of random place in the array
        $votes = array_slice($numbers, mt_rand(0, $v_cnt-$n_votes+1),$n_votes-1);
        // Count what the last item should be
        $votes[] = $v_cnt - array_sum($votes);
    }
    echo array_sum($votes) . "\n";
    Var_dump($votes);
    

    https://3v4l.org/2h7DB

    看起来很有趣,如果我在代码中包含 $i,我们可以看到循环中需要多少次尝试才能创建唯一数组。 https://3v4l.org/mPae5
    请记住,此代码对与投票数相反的最大限制非常敏感。
    如果您的 $v_cnt 相对较低而 $n_votes 较高,则可能永远找不到所需的数字。
    只需尝试在最新链接中将 $n_votes 设置为 5,您可以看到 $i 数字可以是 100+(这意味着需要超过 100 个循环才能获得正确的数字集)。

    【讨论】:

    • 谢谢你,不敢相信我只是看了一下。
    • 响应您的编辑,再次查看它,您是对的,我非常小心地尝试捕获会导致问题的值,因此通过快速检查,我已经做了几次。
    • 感谢您抽出宝贵时间提供帮助,感谢您的努力。我会尽快运行您的代码并回复您。
    • 所以经过一些测试,它完全符合我的需要。谢谢。
    • 没问题!再说一遍,我说的还不够,不必对一小部分数字投太多票。
    【解决方案2】:

    这就是我的处理方式......

    $vote_limit = $v_cnt;
    $numbers_required = 3;
    
    for($i=1;$i<=$numbers_required;$i++)
    {
    
        if($i != $numbers_required)
        {
    
            $votes[$i] = mt_rand(0, $vote_limit);
            $vote_limit -= $votes[$i];
    
        } else {
    
            $votes[$numbers_required] = $v_cnt - array_sum($votes);
    
        }
    
    }
    
    echo $votes[1]; // First
    echo $votes[2]; // Second
    echo $votes[3]; // Third
    

    【讨论】:

    • 我喜欢这种改进的方法,但是请您向我解释一下这行 $v_cnt = $vote_limit = 100;
    • 对不起,那是我测试你的时候。我已经更新了我的答案以删除它。
    • 没问题,你知道让每个数字不同的方法吗,我总是需要多数票或获胜票,所以例如不能有 20、20、10,而 21、20、9 会没事。
    • 嗯,这增加了一点复杂性,但也许在第一次调用mt_rand($min, $max) 时将$min 设置为ceil($vote_limit/2) 类似的东西......玩得开心!
    • 您应该包含一些 cmets 或对您的代码与 OP 的不同之处的描述。仅仅转储代码不是回答问题的合适方式。
    猜你喜欢
    • 2018-11-16
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 2018-10-28
    • 2018-08-19
    • 1970-01-01
    • 2011-07-08
    • 2020-07-09
    相关资源
    最近更新 更多