2011-05-13 9 views
5

rand(n) devuelve un número entre 0 y n. ¿Funcionará el rand según lo esperado, con respecto a la "aleatoriedad", para todos los argumentos hasta el límite de entero en mi plataforma?¿Cuán grande puede ser el argumento para el rand de Perl?

+2

Para obtener más información, encontré esto intrigante: http://wellington.pm.org/archive/200704/randomness/index.html – vol7ron

Respuesta

8

esto va a depender de su valor randbits:

rand llama generador de números aleatorios de su sistema (o lo que uno se compilados en su copia de Perl). Para esta discusión, llamaré al generador RAND para distinguirlo de rand, la función de Perl. RAND produce un número entero de 0 a 2 ** randbits - 1, inclusive, donde randbits es un pequeño entero . Para ver qué es lo que está en su perl, use el comando 'perl -V: randbits'. Los valores comunes son 15, 16 o 31.

Cuando llama a rand con un argumento arg, perl toma ese valor como un entero y calcula este valor.

     arg * RAND 
      rand(arg) = --------------- 
         2**randbits 

Este valor siempre estará dentro del rango requerido.

  0 <= rand(arg) < arg 

Pero como arg se hace grande en comparación con 2 ** randbits, las cosas se vuelven problemática. Imaginemos una máquina donde randbits = 15, por lo que RAND tiene rangos de desde 0..32767. Es decir, cada vez que llamamos RAND, obtenemos uno de 32768 valores posibles. Por lo tanto, cuando llamamos rand (arg), obtenemos uno de 32768 valores posibles.

+1

Para acceder a randbits desde dentro de perl, 'use Config; print $ Config :: Config {'randbits'} '. randbits es 15 para MSWin32, 48 para la mayoría de las otras plataformas. – ysth

+1

@ysth También hay perl -V: randbits –

+1

Sí, eso se menciona en la respuesta, pero sería un poco tonto usar eso desde adentro ... – ysth

2

Depende de la cantidad de bits utilizados por el generador de números (pseudo) aleatorio de su sistema. Puede encontrar este valor a través de

perl -V:randbits 

o dentro de un programa a través de

use Config; 
my $randbits = $Config{randbits}; 

rand puede generar 2^randbits números aleatorios distintos. Si bien puedes generar números mayores a 2^randbits, no puedes generar todos los valores enteros en el rango [0, N) cuando N> 2^randbits.

Los valores de N que no tienen una potencia de dos también pueden ser problemáticos, ya que la distribución de los valores aleatorios (enteros truncados) no será plana. Algunos valores estarán ligeramente sobrerrepresentados, mientras que otros estarán ligeramente subrepresentados.

Vale la pena señalar que Randbits es un miserable 15 en Windows. Esto significa que solo puede obtener 32768 (2 ** 15) valores distintos. Puede mejorar la situación haciendo varias llamadas a rand y la combinación de los valores:

use Config; 
use constant RANDBITS => $Config{randbits}; 
use constant RAND_MAX => 2**RANDBITS; 

sub double_rand { 
    my $max = shift || 1; 
    my $iv = 
      int rand(RAND_MAX) << RANDBITS 
     | int rand(RAND_MAX); 
    return $max * ($iv/2**(2*RANDBITS)); 
} 

randbits Suponiendo = 15, double_rand imita randbits = 30, proporcionando 1073741824 (2 ** 30) posibles valores distintos. Esto alivia (pero nunca puede eliminar) los dos problemas mencionados anteriormente.

0

Estamos hablando de grandes enteros aleatorios y de si es posible obtenerlos. Cabe señalar que la concatenación de dos enteros aleatorios también es un entero aleatorio.Así que si su sistema, por cualquier razón, no puede ir más allá 999999999999, a continuación, sólo escribir

$bigrand = int(rand(999999999999)).int(rand(999999999999)); 

y obtendrá un número entero aleatorio de (máximo) el doble de la longitud.

(En realidad esto no es una respuesta numérica a la pregunta “¿qué tan grande un número rand puede ser”, sino más bien la respuesta “se puede llegar tan grande como desee, simplemente concatenar números pequeños”.)

+3

Bienvenido a Desbordamiento de pila. Lo que está sugiriendo como respuesta está cubierto por una de las dos respuestas existentes, y la respuesta lo cubre bastante mejor. Si fuera a usar su técnica, debería asegurarse de que la segunda parte del número tenga el prefijo de ceros suficientes. Has elegido 12 dígitos en el ejemplo, lo que es probable que cause algunos problemas; 9 dígitos serían más seguros. Probablemente necesites usar 'sprintf ("% d% 09d ", rand (999_999_999), rand (999_999_999))' para generar la cadena. Incluso eso podría ser problemático en Windows; ver las otras respuestas de por qué. –

Cuestiones relacionadas