PHP, nasıl büyük bir yalancı rasgele sayı üretmek mi?

12 Cevap php

PHP ile bir big rasgele sayı gibi bir şey oluşturmak için bir yol arıyorum:

mt_rve($lower, $upper);

Yakından gördüm gmp_rveom () ancak beni alt ve üst sınırları (Ben ne olduğunu hiç bir fikrim yok) uzuv başına bit sadece sayısını belirtmek için izin vermez.

EDIT: Axsuuls answer seems to be pretty close to what I want ve very similar to gmp_rveom however there seems to be only one flaw in one scenario.

Ben arasında rastgele bir numara almak için wan't varsayalım:

  • 1225468798745475454898787465154

ve:

  • 1225468798745475454898787465200

Yani fonksiyon denir eğer BigRveomNumber ():

BigRveomNumber($length = 31);

Bu kolayca belirtilen sınır dışında hangi 9999999999999999999999999999999 dönebilirsiniz.

How can I use a min / max boundary instead of a length value?

BigRveomNumber('1225468798745475454898787465154', '1225468798745475454898787465200');

Bu 1225468798745475454898787465 [154 .. 200] arasında rastgele bir sayı döndürür.

Referans için ben çözüm function supplied in this question faydalanmak gerekebilir inanıyorum.

EDIT: Yukarıdaki sonrası silindi, işte burada:

function compvardır($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;
  }
}

12 Cevap

Aşağıdaki deneyin:

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);
}

Rastgele bir yüzde ile minimum ve maksimum arasındaki farkı çarpın, ve (int yuvarlama ile) minimum ekleyin: matematik aşağıdaki gibidir.

Ne gerçekten bilmeniz gereken göreli boşluğudur; o zaman 0'dan maksimum boşluğu bir sayıda üretebilirsiniz küçük ise o kadar az ekleyin.

Bu size dev rasgele sayı daha sıfır verecek ve siz de (aynı zamanda kolayca uygulanabilir ki, dev rasgele sayı 0 ile başlayabilirsiniz? Değilse) dev rasgele sayının uzunluğunu belirleyebilirsiniz

<?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;

?>

İyi şanslar!

Ne yapabileceğiniz birkaç küçük rasgele sayılar oluşturmak ve bunları birleştirmek olduğunu. Aslında olsa gerek ne kadar büyük emin değil.

$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);

Tamamen denenmemiş :-)

Bu sizin için işe yarayabilecek. (Bunu neden ihtiyaç emin değilim, bu yüzden bunu yapmak için en iyi yol olmayabilir, ama ihtiyaçlarınızı uygun olmalıdır):

<?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;
}

Ben bir kaç kez denedim ve Tamam çalışıyor gibi görünüyor. Gerekirse Optimize. Fikir kabul edilebilir aralıkta vereceğini rastgele sayı için rasgele uzunluk bulmaktan tarafından başlamaktır. Sonra birleştirerek o uzunluğa kadar tek rastgele rakamlar birini oluşturabilir. Bu aralıkta değilse, aralığında rasgele yeni bir rakam oluşturmak ve birleştirmek.

Ben PHP string fonksiyonları yararlanmak için bir dizi için bir dize dönüştürmek olacağı gerçeğini kullanın. Tabii ki bu mt_rand için bir uyarı oluşturur, ama biz sadece numaraları kullanmak gibi, onu bastırmak için güvenli olmalıdır.

Şimdi, ben size ilk etapta bu ihtiyacı neden olarak oldukça meraklı olduğumu söylemek zorundayım.

/* 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;
}

Bu rand_range($min, $max) = $min + rand() % ($max - $min) keyfi duyarlıklı aritmetik tercüme sadece klasik formüldür. $max - $min iki güç değilse bu sapma belirli bir miktar sergileyebilirler ancak rastgele bit sayısının büyüklüğüne kıyasla yeterince yüksek ise, $max - $min eğilim haline ihmal edilebilir.

Bu işe yarayabilir:

  • Max rand sayı benim makinede 2147483647 çünkü 9 sayı veya daha az olan bir diziye numarası ("rest") ... 9 karakter ayrıldı.
  • Her "9-ya da-daha az sayıda dizi blok" için, rasgele bir sayı oluşturmak.
  • Dizi implode ve artık kullanılabilir bir rasgele sayı olacaktır.

Fikiri örnek kod (not: kodu geri olduğunu)

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);
}

Denendi ve çalışıyor

<?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;
}

?>

Yaratma rastgele karakter 'n' olarak gerçekten rastgele bir seçenek, ('9999999999 ') değil hala, teorik, 1 geri dönebilir ...

Burada oldukça basit bir fonksiyon:

function bcrand($max) { 
    return bcmul($max, (string)mt_rand() / mt_getrandmax() ); 
}

Sadece ölçeğini ayarlamak, rastgele N bit değil dönecektir unutmayın

Lütfen kürsüye ve ve buna aralığında rastgele numara.

1225468798745475454898787465154 + rand(0, 6)

İşte pseudocode:


// 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

Notlar:

  • (ikinci satırda hariç) burada tüm aritmetik keyfi hassas olması gerekir: Bu BCMath kütüphane kullanımı
  • ikinci satırında, "uzunluk" basamak sayısı, yani 1025 "uzunluk" 4 olurdu