PHP で大きな擬似乱数を生成するにはどうすればよいですか?
質問
を生成する方法を探しています 大きい PHP での乱数。次のようなものです。
mt_rand($lower, $upper);
私が見た中でより近くにあるのは、 gmp_random() ただし、下限と上限を指定できるのは、四肢あたりのビット数だけです (これが何なのかはわかりません)。
編集:Axsuulsの答えは私が望むものにかなり近く、gmp_randomに非常に似ているようですが、1つのシナリオには欠陥が1つだけあるようです。
次の間で乱数を取得したくないとします。
- 1225468798745475454898787465154
そして:
- 1225468798745475454898787465200
したがって、関数が呼び出された場合 大きな乱数():
BigRandomNumber($length = 31);
これにより、指定された境界外の 9999999999999999999999999999999 が簡単に返されます。
長さの値の代わりに最小/最大境界を使用するにはどうすればよいですか?
BigRandomNumber('1225468798745475454898787465154', '1225468798745475454898787465200');
これにより、次の範囲の乱数が返されます。 1225468798745475454898787465 [154 .. 200].
参考までに、解決策は次のものを利用する必要があると思います。 この質問で提供されている関数.
編集:上記の投稿は削除されましたが、次のとおりです。
function compare($number1, $operator, $number2) {
$x = bccomp($number1, $number2);
switch($operator) {
case '<':
return -1===$x;
case '>':
return 1===$x;
case '=':
case '==':
case '===':
return 0===$x;
case '!=':
case '!==':
case '<>':
return 0!==$x;
}
}
解決
次を試してみます:
function BigRandomNumber($min, $max) {
$difference = bcadd(bcsub($max,$min),1);
$rand_percent = bcdiv(mt_rand(), mt_getrandmax(), 8); // 0 - 1.0
return bcadd($min, bcmul($difference, $rand_percent, 8), 0);
}
数学は以下の通りである:ランダムな割合で最小値と最大値との差を乗算し、(intに丸めで)最小に追加
他のヒント
あなたが本当に知っておく必要があることは相対的なギャップがあります。それは小さなだならば、あなたは0から最大ギャップに番号を生成することができ、その最小にを追加します。
このあなたの巨大な乱数でより多くのゼロを与えるだろう、あなたはまた、巨大な乱数の長さを指定することができます(あなたの巨大な乱数でも容易に実現できるよう、0で始まる?もしできません)
<?php
$randNumberLength = 1000; // length of your giant random number
$randNumber = NULL;
for ($i = 0; $i < $randNumberLength; $i++) {
$randNumber .= rand(0, 9); // add random number to growing giant random number
}
echo $randNumber;
?>
グッドラック!
あなたにできることはいくつかの小さな乱数を作成し、それらを組み合わせることです。あなたが実際にかかわらず、必要があるか大にわからない。
$lower = gmp_com("1225468798745475454898787465154");
$upper = gmp_com("1225468798745475454898787465200");
$range_size = gmp_sub($upper, $lower);
$rand = gmp_random(31);
$rand = gmp_mod($rand, $range_size);
$result = gmp_add($rand, $lower);
完全にテストされていない: - )
これはあなたのために働くかもしれません。 (私はあなたがそれを必要とする理由わからないので、それはそれを行うための最善の方法ではないかもしれませんが、それはあなたの要件に合わせなければならない):
<?php
function bigRandomNumber($min, $max)
{
// check input first
if ($max < $min) { return false; }
// Find max & min length of the number
$lenMin = strlen ($min);
$lenMax = strlen ($max);
// Generate a random length for the random number
$randLen = $lenMin + mt_rand(0, $lenMax - $lenMin);
/* Generate the random number digit by digit,
comparing it with the min and max values */
$b_inRange = false;
for ($i = 0; $i < $randLen; $i++)
{
$randDigit = mt_rand(0,9);
/* As soon as we are sure that the number will stay
in range, we can stop comparing it to min and max */
if (!$b_inRange)
{
$tempRand = $rand . $randDigit;
$tempMin = substr($min, 0, $i+1);
$tempMax = substr($max, 0, $i+1);
// Make sure that the temporary random number is in range
if ($tempRand < $tempMin || $tempRand > $tempMax)
{
$lastDigitMin = substr($tempMin, -1);
$lastDigitMax = substr($tempMax, -1);
$tempRand = $rand . @mt_rand($lastDigitMin, $lastDigitMax);
}
/* Check if $tempRand is equal to the min or to the max value.
If it is not equal, then we know it will stay in range */
if ($tempRand > $tempMin && $tempRand < $tempMax)
{
$b_inRange = true;
}
}
else
{
$tempRand = $rand . $randDigit;
}
$rand = $tempRand;
}
return $rand;
}
私は数回を試み、それがOK働くように見えます。必要に応じて最適化します。アイデアは許容範囲内にそれを置くでしょう、あなたの乱数のためのランダムな長さを把握することから始めることです。そして、連結することにより、その長さまで1によって乱数1を生成します。それが範囲内にない場合は、範囲とCONCATENATEで新しいランダムな数字を生成します。
私は、PHPは文字列関数を利用するために文字列を数値に変換するという事実を使用しています。もちろん、これはmt_randに対して警告を生成しますが、我々は数字のみを使用して、それを抑制するのが安全である必要があります。
さて、私はあなたが最初の場所でこれを必要とする理由として、非常に好奇心と言わざるを得ないます。
/* Inputs:
* min - GMP number or string: lower bound
* max - GMP number or string: upper bound
* limiter - GMP number or string: how much randomness to use.
* this value is quite obscure (see `gmp_random`, but the default
* supplies several hundred bits of randomness,
* which is probably enough.
* Output: A random number between min (inclusive) and max (exclusive).
*/
function BigRandomNumber($min, $max, $limiter = 20) {
$range = gmp_sub($max, $min);
$random = gmp_random();
$random = gmp_mod($random, $range);
$random = gmp_add($min, $random);
return $random;
}
これは、任意精度演算に翻訳だけ古典式rand_range($min, $max) = $min + rand() % ($max - $min)
あります。 $max - $min
が2のべき乗でない場合、それはバイアスの一定量を示すことができるが、乱数のビット数は$max - $min
の大きさに比べて十分に高い場合、バイアスは無視できるようになる。
これはうまくいくかもしれません:
- 数値を 9 個以下の配列 (「残り」) に分割します...私のマシンでは最大ランド数が 2147483647 なので、9 文字です。
- 「9 個以下の数字の配列ブロック」ごとに、乱数を作成します。
- 配列を分解すると、使用可能な乱数が得られます。
このアイデアを説明するコード例 (注意:コードは元に戻されます)
function BigRandomNumber($min,$max) {
// Notice: Will only work when both numbers have same length.
echo (strlen($min) !== strlen($max)) ? "Error: Min and Max numbers must have same length" : NULL;
$min_arr = str_split($min);
$max_arr = str_split($max);
// TODO: This loop needs to operate on 9 chars ($i will increment by $i+9)
for($i=0; $i<=count($max_arr); $i++) {
if($i == 0) {
// First number: >=first($min) and <=first($max).
$new_arr[$i] = rand( $min_arr[0], $max_arr[0]);
} else if($i == count($max_arr)) {
// Last number <= $max .. not entirely correct, feel free to correct it.
$new_arr[$i] = rand(0, substr($max,-1));
} else {
$new_arr[$i] = rand(0,9);
}
}
return implode($new_arr);
}
テストおよび作品
<?php
$min = "1225468798745475454898787465154";
$max = "1225468798745475454898787465200";
$bigRandNum = bigRandomNumber($min,$max);
echo "The Big Random Number is: ".$bigRandNum."<br />";
function bigRandomNumber($min,$max) {
// take the max number length
$number_length = strlen($max);
// Set the counter
$i = 1;
// Find the base and the min and max ranges
// Loop through the min to find the base number
while ($i <= $number_length) {
$sub_string = substr($min, 0, $i);
// format pattern
$format_pattern = '/'.$sub_string.'/';
if (!preg_match($format_pattern, $max)) {
$base = $sub_string;
// Set the min and max ranges
$minRange = substr($min, ($i - 1), $number_length);
$maxRange = substr($max, ($i - 1), $number_length);
// End while loop, we found the base
$i = $number_length;
}
$i++;
}
// find a random number with the min and max range
$rand = rand($minRange, $maxRange);
// add the base number to the random number
$randWithBase = $base.$rand;
return $randWithBase;
}
?>
の生成 'n' をランダム文字のランダムな( '9999999999')はまだ、理論的には、
... 1を返すことができて、本当にオプションではありませんここでは、非常に簡単な関数です。
function bcrand($max) {
return bcmul($max, (string)mt_rand() / mt_getrandmax() );
}
それは、ランダム性のNビットを返すだけの規模を調整しないことに注意してください。
あなたの床と、それまでの範囲であなたの乱数を取ります。
1225468798745475454898787465154 + rand(0, 6)
これが疑似コードです:
// generate a random number between N1 and N2
rangesize = N2 - N1 + 1
randlen = length(rangesize) + 4 // the 4 is to get more digits to reduce bias
temp = BigRandomNumber(randlen) // generate random number, "randlen" digits long
temp = temp mod rangesize
output N1 + temp
ノート:
- ここでのすべての算術演算 (2 行目は除く) は任意の精度でなければなりません。これにはbcmathライブラリを使用してください
- 2行目の「長さ」は桁数なので、1025の「長さ」は4になります。