エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

疑似乱数を、再現可能な値にする方法【120日目】

何が嬉しいの?

擬似乱数を再現可能にすると、
バグとかの再現も出来る。

ドキュメント

PHP: mt_srand - Manual

PHP: mt_rand - Manual

結論

$seed = 10;
mt_srand($seed);
echo mt_rand(0, 255);
echo mt_rand(0, 255);
echo mt_rand(0, 255);

mt_srand($seed);
echo mt_rand(0, 255);
echo mt_rand(0, 255);
echo mt_rand(0, 255);

実行結果

php > $seed = 10;
php > mt_srand($seed);
php > echo mt_rand(0, 255);
9
php > echo mt_rand(0, 255);
125
php > echo mt_rand(0, 255);
228
php >
php > mt_srand($seed);
php > echo mt_rand(0, 255);
9
php > echo mt_rand(0, 255);
125
php > echo mt_rand(0, 255);
228

どういうこと?

mt_srandにシード値と呼ばれる値を入れると、
そのシード値に合わせた乱数のテーブルが出来上がる。

シード値が同じであれば、
乱数の出てくる順番が同じものになるわけです。

応用

暗号もどき。シード値を共有すれば暗号っぽくなるのかな。

<?php
    $seed = "20";

    $word = "ABCDEFGabcdefg";
    check_enc($word, $seed);

    $word = <<<EOF
    テストの文です。
    これではどうなるでしょうか。
EOF;
    check_enc($word, $seed);

    function check_enc($word, $seed)
    {
        $en = enc2($word, $seed);
        $de = dec2($en, $seed);

        echo "元の文字列:" . $word . PHP_EOL;
        echo "暗号化した文字列:" . $en . PHP_EOL;
        echo "複合した文字列:" . $de . PHP_EOL;

        if ($de === $word) {
            echo "OK!" . PHP_EOL;
        } else {
            echo "NG!" . PHP_EOL;
        }
    }

    //文字を配列に変えてforeach
    //ASCII文字に変換→1足してずらす→文字に戻す
    //配列を文字列に戻す
    function enc2($word, $seed)
    {
        mt_srand($seed, MT_RAND_MT19937);
        foreach(str_split($word) as $char) {
            $char_array[] = chr(ord($char) + mt_rand(0, 255));
        }
        $encripted = implode($char_array);
        return $encripted;
    }

    function dec2($encripted, $seed)
    {
        mt_srand($seed, MT_RAND_MT19937);
        foreach(str_split($encripted) as $char) {
            $char_array[] = chr(ord($char) - mt_rand(0, 255));
        }
        $word = implode($char_array);
        return $word;
    }

実行結果

元の文字列:ABCDEFGabcdefg
暗号化した文字列:�R#� ��y�F�
複合した文字列:ABCDEFGabcdefg
OK!
元の文字列:    テストの文です。
    これではどうなるでしょうか。
暗号化した文字列:��/�]w��*%hY���������gWs��&�^���L��h����l�.���O۬7��q�I�Y3�@���
複合した文字列:    テストの文です。
    これではどうなるでしょうか。
OK!