web-dev-qa-db-ja.com

mt_Rand()とRand()の違い

速度に関するmt_Rand($min, $max)Rand($min, $max)の使用の違いは何ですか?

31
Thomas Rbt

更新

PHP 7.1 mt_RandRandに完全に取って代わり、Randmt_Randのエイリアスになりました。以下の回答は、古いバージョンの2つの関数の違いとmt_Randを導入する理由に焦点を当てています。


mt_Randが導入された理由は速度ではありませんでした!

Rand関数はmt_Randの前に存在していましたが、重大な欠陥がありました。 A PRNGいくつかのエントロピーを取得する必要があります。これは乱数のシーケンスを生成する数値です。Rand()によって生成された10個の数値のリストを出力する場合:

for ($i=0;$i<10;++$i)
    echo Rand(), PHP_EOL;

出力を使用して、Randシードが何であったかを調べることができ、それを使用して、次の乱数を予測できます。これを行うツールがありますので、少しグーグルでテストしてください。

ここに示されているように、Randには、そのパターンの乱数 が比較的迅速に表示されるという問題もありますmt_Randの問題も、はるかに改善されているようです。

mt_Randは、より良いランダム化アルゴリズム(Mersenne Twist)を使用します。これは、シードを決定する前に、より多くの乱数を知る必要があります and は高速です。 これは、定義により、mt_RandRand is よりも高速であることを意味するものではなく、数値の生成方法が高速であり、ここでの他の回答が示しているように、関数のパフォーマンスに実際の影響はありません。
どちらの方法でも、 mt_srandsrand docs をご覧ください。もっと情報が含まれていると確信しています

mt_Randのアルゴリズムがパフォーマンスの向上につながる場合、それはあなたにとって素晴らしいことですが、それは幸運な偶然です。 TL; TR:

mt_Randは、Randに存在する問題を修正するために導入されました!

48

アップデート(PHP 7.1):

Rand()srand()は、それぞれmt_Rand()mt_srand()のエイリアスになりました。 これは、次の関数の出力には変更があります:Rand()shuffle()str_shuffle()、およびarray_Rand()

つまり、バージョン7.1以降では、 Randmt_Randを内部的に呼び出すため 、両者の間に実質的な違いはありません。


前PHP 7.1:

Rand()を使用することは、セキュリティ目的で使用しない場合、悪い習慣ではありません。通常、Rand()(習慣?)を使用しています。

大量の乱数が必要な場合は、Randの代わりにmt_Randが必要になります。 mt_Randの期間は2です19937 − 1、Rand(232)。 Randおよびmt_Randを使用したグラフィカルパターン生成については、 この記事 をご覧ください。

Periodicity および entropymt_Rand()の代わりにRand()を使用する唯一の理由ですセキュリティや速度の改善ではありません。

数学的にmt_Randは、Rand(2)よりも多く エントロピー およびより大きい 周期性19937−1対232)。

あなたは、いくつかの乱数を必要とし、セキュリティが問題、Randでない場合(クリーンアッププロセスを発射決定する乱数を取得する)仕事を行います。


テスト速度の改善

実際には、2つの関数の速度に大きな違いはありません(おそらくPHP⇔Cラッパーのオーバーヘッドのためでしょうか?)。

PHPテストコード:

<?php
for ($c = 0; $c < 3; $c++) {
  $start = microtime(true);
  $sum = 0.0;
  for ($i = 0; $i < 100000000; $i++) {
    $sum += Rand();
  }
  printf('[Rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}
for ($c = 0; $c < 3; $c++) {
  $start = microtime(true);
  $sum = 0.0;
  for ($i = 0; $i < 100000000; $i++) {
    $sum += mt_Rand();
  }
  printf('[mt_Rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}

PHP 7.0.19:でのテスト

$ php timing.php
[Rand 0] Time: 4.658 s
[Rand 1] Time: 4.664 s
[Rand 2] Time: 4.654 s
[mt_Rand 0] Time: 4.267 s
[mt_Rand 1] Time: 4.255 s
[mt_Rand 2] Time: 4.261 s

PHP 5.4.45(低速のマシン):でのテスト

$ php timing.php
[Rand 0] Time: 10.862 s
[Rand 1] Time: 10.889 s
[Rand 2] Time: 10.615 s
[mt_Rand 0] Time: 10.948 s
[mt_Rand 1] Time: 9.883 s
[mt_Rand 2] Time: 10.190 s

主張どおり400%ではなく6-9%のみ。


セキュリティ目的で使用する

ただし、セキュリティの問題のためにアプリケーションで多くのエントロピーが必要な場合は、より安全な方法が必要であり、 openssl_random_pseudo_bytes() が最善のソリューションであり、その作業を行います(はるかに良いが遅い?速度よりもセキュリティが必要?) openssl関連の問題に依存している

Rand()mt_Rand() も十分に安全ではありません

Cautionこの関数は暗号的に安全な値を生成しないため、暗号化の目的には使用しないでください。暗号的に安全な値が必要な場合は、代わりにrandom_int()random_bytes()、またはopenssl_random_pseudo_bytes()の使用を検討してください。

PHP random_compat のような拡張機能がありますが、必要でない場合は使用しないことをお勧めします。

24
OscarGarcia

PHP 7.1の時点でまったく違いはありません。Rand()はmt_Rand()のエイリアスになりました。

http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.Rand-sr​​and-aliases を参照してください

その他の詳細: https://wiki.php.net/rfc/rng_fixes

1
Bell

mt_Rand() のPHPマニュアルは次のように述べています:

これは、平均的なlibc Rand()が提供するものの4倍の速度で乱数を生成します。

1
Forien