dtudj42064 2019-05-05 08:01
浏览 28

如果它们具有相同的参数,如何在php中生成相同的随机值?

I'm using a function to generate random values using TAG including parameters as Length, type of random : Alphabetic, Numeric or Mix, and LowerCase, Uppercase. Now this issue is that I want to store or save, fix or freeze, a random result to use it in multiples places. For exemple instead of RAND, I use FixRAND, then the result will be the same in the whole page as long as TAG have the same parameters.

To give you a small idea of what I already have. It's fully functional when I use some TAGs Like [RAND,10,A,U] but It generate random values every time. I need to add another TAG that can store some how the same results upon the same request.

function generateRandom($length,$type,$gen){
        switch ($type) {
            case 'A':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }
                break;
            case 'N':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = '0123456789';
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }
                break;
            case 'M':
                $rd= "";
                srand((double)microtime()*1000000);
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
                for($i = 0; $i < $length; $i++){
                    $rd .= substr($data, (rand()%(strlen($data))), 1);
                }

                break;
        }
        if ( $gen == 'U') $rd = strtoupper($rd);
        if ( $gen == 'L') $rd = strtolower($rd);
        return $rd;
    }

$replaced_xxxxxx=str_replace("[MESSAGE]","$message",$replaced_xxxxxx);
preg_match_all("/\[RAND,[0-9]+,[AMN],[LU]\]/",$replaced_xxxxxx,$random_tag_array);
        foreach ($random_tag_array[0] as $random_tag) {
            $random_stripped=$random_tag;
            $random_stripped=str_replace("[RAND,","",$random_stripped);
            $random_stripped=str_replace("]","",$random_stripped);
            $random_exploded=explode(',', $random_stripped);
            $random_generated=generateRandom($random_exploded[0],$random_exploded[1],$random_exploded[2]);
            $replaced_xxxxxx=preg_replace($random_tag, $random_generated, $replaced_xxxxxx,1);
  • 写回答

1条回答 默认 最新

  • douweng7233 2019-05-05 08:12
    关注

    Edit: As @KIKOSoftware points out, my answer was not real random. I modified my answer. This now uses random_int() which cryptographically secure pseudo-random. The results of the random function are now saved together with the input parameters. This is the only way because random_int() is random. This way there is no way to create the same values again so they have to be saved.

    This solution takes more memory because it needs to save more values. But this one is random. You may choose between both solutions. If you are trying to get random examples the original solution is enough. For things that need to be secure (e.g. password handling ect.) you should use the new solution.

    Note: Requires PHP 7+. If you are working with a lower version there is a backporting function on php.net in the comments.

    function generateRandom($length, $type, $gen){
        switch ($type){
            case 'A':
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
                break;
            case 'N':
                $data = '0123456789';
                break;
            case 'M':
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
                break;
            default: 
                $data = "";
                break;
        }
    
        static $randoms = array();
    
        $rd = "";
        $max = strlen($data) - 1;
        for($i = 0; $i < $length; $i++){
            $rd_key = $length.$type.$gen.$i;
            if(!isset($randoms[$rd_key])){
                $randoms[$rd_key] = random_int(0, $max);
            }
            $rd .= $data[$randoms[$rd_key]];
        }
    
        if ( $gen == 'U') $rd = strtoupper($rd);
        if ( $gen == 'L') $rd = strtolower($rd);
    
        return $rd;
    }
    

    Example Result

    enter image description here

    Generated with code:

    print("<table>".
            "<tr>".
                "<th>Function</th>".
                "<th>Secure result</th>".
                "<th>Secure is correct</th>".
                "<th>Normal result</th>".
                "<th>Normal is correct</th>".
            "</tr>");
    $cache_normal = array();
    $cache_secure = array();
    // 12 possibilities, there has to be one double element
    for($i = 0; $i < 13; $i++){
        $length = rand(3, 5);
        $type = rand(0, 2);
        switch($type){
            case 1: $type = "N"; break;
            case 2: $type = "M"; break;
            case 0: 
            default: $type = "A"; break;
        }
        $gen = rand(0, 1);
        switch($gen){
            case 1: $gen = "U"; break;
            case 0: 
            default: $gen = "L"; break;
        }
    
        $secure = generateRandomSecure($length, $type, $gen);
    
        if(!isset($cache_secure[$length.$type.$gen])){
            $cache_secure[$length.$type.$gen] = $secure;
            $secure_corr = "-";
        }
        elseif($cache_secure[$length.$type.$gen] == $secure){
            $secure_corr = "<i>found and correct</i>";
        }
        else{
            $secure_corr = "<i>found but wrong</i>";
        }
    
        $normal = generateRandom($length, $type, $gen);
        if(!isset($cache_normal[$length.$type.$gen])){
            $cache_normal[$length.$type.$gen] = $normal;
            $normal_corr = "-";
        }
        elseif($cache_normal[$length.$type.$gen] == $normal){
            $normal_corr = "<i>found and correct</i>";
        }
        else{
            $normal_corr = "<i>found but wrong</i>";
        }
    
        print("<tr>".
                "<td><code>generateRandom(".$length.", ".$type.", ". $gen.")</code></td>".
                "<td>'".$secure."'</td>".
                "<td>".$secure_corr."</td>".
                "<td>'".$normal."'</td>".
                "<td>".$normal_corr."</td>".
            "</tr>"
        );
    }
    print("</table>");
    

    Original answer: I think I would store the seed of the random. You can use a static (or global) variable which contains the parameters as the keys and the seed as the value.

    function generateRandom($length, $type, $gen){
        static $seeds = array();
        if(!isset($seeds[$length.$type.$gen])){
            $seeds[$length.$type.$gen] = microtime(true) * 1000000;
        }
        srand($seeds[$length.$type.$gen]);
        $rd = "";
    
        switch ($type) {
            case 'A':
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
                break;
            case 'N':
                $data = '0123456789';
                break;
            case 'M':
                $data = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
                break;
            default: 
                $data = "";
                break;
        }
    
        $len = strlen($data);
        for($i = 0; $i < $length; $i++){
           $rd .= $data[rand() % $len];
        }
    
        if ( $gen == 'U') $rd = strtoupper($rd);
        if ( $gen == 'L') $rd = strtolower($rd);
    
        return $rd;
    }
    

    This code results in the following. I hope this is what you are trying to do:

    var_dump(generateRandom(3, "A", "L")); // prints e.g. string(3) "wkr"
    var_dump(generateRandom(4, "A", "L")); // prints e.g. string(3) "rppd"
    var_dump(generateRandom(4, "N", "L")); // prints string(4) "9377"
    var_dump(generateRandom(3, "A", "L")); // prints string(3) "wkr" again
    

    After a reload all the values are different again (because the seeds change).

    评论

报告相同问题?

悬赏问题

  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 正弦信号发生器串并联电路电阻无法保持同步怎么办
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序