0

私は、MySQL データベースに時折エントリを挿入するこの小さな内部プロジェクトを持っています。「idChar」という名前の列があり、その値を長さ31の62文字を使用してランダムに生成された文字列に設定しました。

今日、新しいエントリが、たまたま数か月前のエントリとまったく同じ idChar を持っていることを発見しました。保存する前に重複エントリをチェックしていますが、これが発生する可能性について考えさせられました。これらのランダムキーを生成する実装に欠陥があるかどうか知りたいです. 複製を取得すると、おおよそ 62^31 分の 1 になるはずですよね?

function getCode($len)
{
    //$len = 10;
    $base='ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz123456789';
    $max=strlen($base)-1;
    $linkCode='';
    mt_srand((double)microtime()*1000000);
    while (strlen($linkCode)<$len+1)
      $linkCode.=$base{mt_rand(0,$max)};

    return $linkCode;
}

$idChar=getCode(30);

//code to insert into MySQL here
4

1 に答える 1

1

重複を取得する確率は、誕生日の問題に従って計算されます。これは、離散コドメインからランダムに選択された出力を生成する関数の出力の衝突の可能性を計算する方法であるためです。実際には、ランダムに行われた選択のプールの中で、任意の 2 つの選択が同じである可能性を計算したいと考えています。

また、コールは不要なので完全に削除するmt_srand必要があります。これにより、PHP が自動的に行うシードよりも悪いシードが提供される可能性があります。microtime(少なくとも私のシステムでは)の出力は次のようになると考えてください

0.29574400 1348356024

これは、float の最後の 2 桁が常にゼロであり、キャストが秒の部分を完全に無視するため、100 万の異なるシードしか利用できないことを意味します(double)microtime()(いずれにせよ、お粗末なシードになります)。

乱数ジェネレーターが同じシードでシードされるたびに同じ乱数シーケンスを生成すると仮定すると、実際には、62^31 ではなく 100 万の可能なランダム コードしかありません。かなりの減少です! 幸いなことに、これはPHP 5.2.1 以降では発生しないことが文書化されています。

于 2012-09-22T23:21:07.693 に答える