この記事では主に、PHP における擬似乱数と真の乱数の詳細な説明を紹介します。この記事では、最初に真の乱数と擬似乱数の関連概念を説明し、より良い擬似乱数を生成する方法について説明します。 mt_rand() 関数を使用するよりも、サンプルコードを使用します。お役に立てれば幸いです。
最初に述べておく必要があるのは、コンピューターは完全な乱数を生成することはできず、「疑似乱数」しか生成できないということです。実際、絶対乱数は理想的な乱数にすぎません。コンピュータがどのように発達しても、完全に乱数の列は生成されません。コンピュータは比較的ランダムな数、つまり擬似乱数しか生成できません。
擬似乱数は擬似乱数ではありません。ここでの「擬似」は規則的なことを意味します。つまり、コンピューターによって生成される擬似乱数はランダムであり、規則的でもあります。どのように理解すればよいでしょうか?生成された擬似乱数は、特定のルールに従う場合もあれば、どのルールにも従わない場合もあります。一部の疑似乱数は、特定のルールに従いません。例えば、「世界に同じ形の葉は二つとない」ということは、物事の性質、つまりランダム性を指しますが、どの木の葉も同じような形をしている、つまり物事の共通性を指します。 、規則性。この観点から見ると、コンピュータは疑似乱数しか生成できず、完全な乱数を生成することはできないという事実をおそらく受け入れるでしょう。
まず、真の乱数と擬似乱数の概念を理解しましょう。
真性乱数発生器: 英語: true Random Number Generator、略称: TRNG は、予測不可能な物理的方法によって生成される乱数です。
擬似乱数発生器: 英語: pseudo-randomnumbergenerators、略称: PRNG は、特定のアルゴリズムを使用してコンピュータによって生成されます。
2 つの方法で生成された乱数の画像を比較してください。
Random.org (大気ノイズを使用して乱数を生成し、大気ノイズは空中の雷雨によって生成されます) によって生成されたランダム ビットマップ:
Windows で PHP の rand() 関数によって生成されたランダム画像:
明らかに、後者の擬似乱数発生器によって生成された画像には、これらの明らかな縞模様があります。
PHP の rand ランダム関数を使用してこの画像を生成するコードは次のとおりです:
//需要开启gd库 header("Content-type: image/png"); $im = imagecreatetruecolor(512, 512) or die("Cannot Initialize new GD image stream"); $white = imagecolorallocate($im, 255, 255, 255); for ($y=0; $y<512; $y++) { for ($x=0; $x<512; $x++) { if (rand(0,1) === 1) { imagesetpixel($im, $x, $y, $white); } } } imagepng($im); imagedestroy($im);
実際、すべての擬似乱数ジェネレーター (PRNG) がそれほど悪いわけではなく、Windows の () 関数での PHP の rand がたまたま次のようになっているだけです。 。同じコードを Linux でテストすると、結果の画像には明らかな縞模様が表示されません。 Windows では、rand() 関数の代わりに mt_rand() 関数を使用すると、効果が大幅に向上します。これは、mt_rand() がメルセンヌ ツイスター アルゴリズムを使用して乱数を生成するためです。 PHP のドキュメントには、「mt_rand() は、libc が提供する rand() よりも平均 4 倍の速さでランダムな値を生成できる」とも記載されています。
さらに、Linux カーネル (1.3.30 以降) には、多くのセキュリティ目的に十分な乱数ジェネレーター /dev/random が含まれています。
以下は、Linux の乱数ジェネレーターの原理の紹介です:
Linux オペレーティング システムは、本質的にランダムな (または少なくとも強いランダム性を持つコンポーネントを含む) ライブラリ データを提供します。通常、このデータはデバイス ドライバーから取得されます。たとえば、キーボード ドライバーは 2 つのキーを押す間の時間に関する情報を収集し、この周囲のノイズを乱数生成ライブラリに入力します。
ランダム データはエントロピー プールに保存されます (Linux カーネルは、デバイス ドライバーやその他のソースから環境ノイズを収集するためにエントロピー プールを維持します。理論的には、エントロピー プール内のデータは完全にランダムであり、真の乱数シーケンスを生成できます。エントロピー プール内のデータのランダム性を追跡する場合、カーネルはデータをプールに追加するときにデータのランダム性を推定します。このプロセスはエントロピー推定と呼ばれます。エントロピー推定は、プールに含まれる乱数の数を表します。値が大きいほど、プール内のデータはよりランダムになり、新しいデータが入るたびに「撹拌」されます。この撹拌は、実際にはランダム性を改善するのに役立つ数学的変換です。データがエントロピー プールに追加されると、システムは取得した真にランダムなビットの数を推定します。
ランダム性の総量を測定することが重要です。問題は、一部の量が最初に考えたときよりもランダムではないことがよくあることです。たとえば、最後のキーストロークからの秒数を表す 32 ビットの数値を追加しても、ほとんどのキーストロークは互いに近接しているため、実際には新しい 32 ビットのランダム情報は提供されません。
/dev/random からバイトが読み取られた後、エントロピー プールは MD5 アルゴリズムを使用して暗号化ハッシュを実行し、ハッシュ内の個々のバイトが数値に変換されて返されます。
エントロピー プールに利用可能なランダム性のビットがない場合、/dev/random はプールに十分なランダム性が得られるまで、結果を返さずに待機します。つまり、/dev/random を使用して多数の乱数を生成すると、速度が遅すぎて実用的ではないことがわかります。 /dev/random が数十バイトのデータを生成した後、何秒も結果が生成されないことがよくあります。
幸运的是有熵池的另一个接口可以绕过这个限制:/dev/urandom。即使熵池中没有随机性可用,这个替代设备也总是返回随机数。如果您取出许 多数而不给熵池足够的时间重新充满,就再也不能获得各种来源的合用熵的好处了;但您仍可以从熵池的 MD5 散列中获得非常好的随机数!这种方式的问题是,如果有任何人破解了 MD5 算法,并通过查看输出了解到有关散列输入的信息,那么您的数就会立刻变得完全可预料。大多数专家都认为这种分析从计算角度来讲是不可行的。然而,仍然认为 /dev/urandom 比 /dev/random 要“不安全一些”(并通常值得怀疑)。
Windows下没有/dev/random可用,但可以使用微软的“capicom.dll”所提供的CAPICOM.Utilities 对象。
以下是使用PHP时比用mt_rand()函数产生更好的伪随机数的一段例子代码:
<?php // get 128 pseudorandom bits in a string of 16 bytes $pr_bits = ''; // Unix/Linux platform? $fp = @fopen('/dev/urandom','rb'); if ($fp !== FALSE) { $pr_bits .= @fread($fp,16); @fclose($fp); } // MS-Windows platform? if (@class_exists('COM')) { try { $CAPI_Util = new COM('CAPICOM.Utilities.1'); $pr_bits .= $CAPI_Util->GetRandom(16,0); // if we ask for binary data PHP munges it, so we // request base64 return value. We squeeze out the // redundancy and useless ==CRLF by hashing... if ($pr_bits) { $pr_bits = md5($pr_bits,TRUE); } } catch (Exception $ex) { // echo 'Exception: ' . $ex->getMessage(); } } if (strlen($pr_bits) < 16) { // do something to warn system owner that // pseudorandom generator is missing } ?>
所以PHP要产生真随机数 还是要调用外部元素来支持的!
相关推荐:
PHP函数:生成N个不重复的随机数,php 随机数_PHP教程
以上がPHP の true と false の乱数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。