PHP: Números aleatorios
21 de Marzo 2009 – 2:42 pmPHP incorpora 2 rutinas para generar números aleatorios, aunque realmente hay que hablar de números pseudo-aleatorios, ya que dichos números se generan a partir de un algoritmo determinista, es decir, para la misma entrada de datos ofrece la misma salida.
Por ello, surge la necesidad de aportar algo que modifique la salida: una semilla. Pero con ello surge un problema: cada vez que se ejecute el programa con una misma semilla, generará los mismos números aleatorios. Imagina que tienes un array del cual quieres recuperar un elemento al azar, siempre tendrías el mismo elemento.
La solución es usar una semilla que varíe, por ejemplo: el tiempo, usando como semilla el valor devuelto de la función time. Desde PHP 4.2.0 no hace falta inicializar la semilla ya que se hace automáticamente, pero para versiones anteriores de PHP si que es necesario.
Un primera opción para generar números pseudo-aleatorios, está en usar la función rand. Si se quiere inicializar la semilla, hay que usar la función srand.
Ejemplo de recuperar un elemento al azar de un array:
- <?php
- function randElem($array)
- {
- return $array[rand(0,count($array)-1)];
- }
- ?>
Si lo que se desea es simular un problema que requiera aleatoriedad y cuyos números aleatorios sean independientes entre ellos (llegada de coches a un semáforo, probabilidad de que en un grupo de personas haya dos personas que cumplan años el mismo día del año…), la función rand no es muy buena opción, ya que los valores generados presentan dependencia entre si.
Una forma visual de ver esta dependencia, es generar una gran cantidad de números pseudo-aleatorios con la rutina en cuestión y generar un plot con esos números.
La idea de generar un plot es ver si aparecen hiperplanos en el gráfico generado (que indicaría que existe dependencia entre los números generados). Si se realiza un plot en 2D a partir de números generados con la función rand, no se aprecia nada especial, pero si creamos un plot en 3D si que se verán esos hiperplanos:
Haz click en la foto para verla a tamaño completo
Este problema es heredado de usar una rutina basada en “bibliotecas de C antiguas que tienen características dudosas o desconocidas. PHP usa el generador de números aleatorios de libc con la función rand()” (texto extraido de mt_rand).
Si se quiere evitar esta dependencia entre los números, habrá que usar la segunda rutina que tiene PHP para generar los números pseudo-aleatorios. La función a usar es mt_rand. Esta rutina “usa el Mersenne Twister, mecanismo que produce números aleatorios cuatro veces más rápido que el resultado promedio de rand() de libc”. Para inicializar su semilla hay que usar la función mt_srand, aunque recuerdo que desde PHP 4.2.0 no hace falta inicializar la semilla.
Si repetimos el experimento del plot 3D con la función mt_rand, el resultado es el siguiente:
Haz click en la foto para verla a tamaño completo
Finalmente, una función que devuelve un número pseudo-aleatorio entre dos números pasados. Esta función también permite generar números con decimales usando el tercer parámetro:
- <?php
- function aleatorio($menor,$mayor,$decimales=false)
- {
- if($decimales)
- return ((mt_rand(0,mt_getrandmax())/mt_getrandmax())*($mayor-$menor))+$menor;
- else
- return mt_rand($menor,$mayor);
- }
- ?>
Nota: el programa usado para generar el plot 3D ha sido R.


2 Comentarios en “PHP: Números aleatorios”
Hola,
Lo que no entiendo es que tres ejes utilizas para representar los numeros en tres dimensiones. ¿Puedes adjuntar el código de R utilizado?
Saludos,
Por Mario el Jun 16, 2009
Hola @Mario
La verdad es que no ha quedado muy claro :). La idea es tener la muestra con los números generados con la correspondiente rutina en una variable de tipo array. Una vez hecho esto y para poder ver como un valor Xk de la lista de números depende de los valores anteriormente generados, creo el plot3d relacionando tres puntos consecutivos (que se han generado consecutivamente). Por ejemplo, si tenemos una variable llamada muestra con 10000 números pseudo-aleatorios:
La función
plot3dse encarga de crear los puntos en el espacio de manera correlativa con los tres arrays pasados por parámetro. Si te fijas cada array tiene 9998 números:- El primero tiene los primeros 9998 elementos del array
- El segundo tiene los números almacenados en las posiciones del 2 al 9999
- Y el tercero tiene los números almacenados en las posiciones del 3 al 10000
Por lo que el primer punto será la coordenada (muestra[1],muestra[2],muestra[3]). El segundo punto a dibujar será (muestra[2],muestra[3],muestra[4]) y así hasta el último punto (muestra[9998],muestra[9999],muestra[10000]). El resto de parámetros son para poner una etiqueta a cada uno de los ejes.
Un saludo.
Por xanfran el Jun 16, 2009