2009-08-16 12 views
7

¿Es así como PHP implementó la generación de números aleatorios?PHP - ¿Es rand (1,1000) = 1000 tan probable como rand (1,1000) = rand (1,1000)?

decir que quiero para calcular un sí o un no. Cada vez que tengo un cierto porcentaje de probabilidad (digamos: 0,05% para este ejemplo).

hago:

$possibilities = 100/$probabilityPercentage; //$possibilities = 2000 
$yes = rand(1,$possibilities); 

$yesCheck = $possiblities;   //OPTION 1 
$yesCheck = rand(1,$possibilities); //OPTION 2 


($yesCheck == $yes) ? return true : return false; 

¿Da los mismos resultados con cualquiera de las opciones?

Respuesta

11

Deje que los datos hablen por sí mismo.

Código

[email protected]:~$ more rand.php 
<?php 

$randrandsum = 0; 
$randconstsum = 0; 
$count = 20; 
for ($j = 0; $j < $count; $j++) { 
     $randrand = 0; 
     $randconst = 0; 
     for ($i = 0; $i < 10000000; $i++){ 
       $a = rand(1,1000); 
       $b = rand(1,1000); 
       if ($a == $b) $randrand++; 
     } 
     for ($i = 0; $i < 10000000; $i++){ 
       $a = rand(1,1000); 
       $c = 1000; 
       if ($c == $a) $randconst++; 
     } 
     $randrandsum += $randrand; 
     $randconstsum += $randconst; 
     print ($j+1)." RAND-RAND: $randrand RAND-CONST: $randconst\n"; 
} 
print "AVG RAND-RAND: ".($randrandsum/$count); 
print " AVG RAND-CONST: ".($randconstsum/$count)."\n"; 
?> 

Prueba de funcionamiento

[email protected]:~$ php rand.php 
1 RAND-RAND: 10043 RAND-CONST: 10018 
2 RAND-RAND: 9940 RAND-CONST: 10132 
3 RAND-RAND: 9879 RAND-CONST: 10042 
4 RAND-RAND: 9878 RAND-CONST: 9965 
5 RAND-RAND: 10226 RAND-CONST: 9867 
6 RAND-RAND: 9866 RAND-CONST: 9992 
7 RAND-RAND: 10069 RAND-CONST: 9953 
8 RAND-RAND: 9967 RAND-CONST: 9862 
9 RAND-RAND: 10009 RAND-CONST: 10060 
10 RAND-RAND: 9809 RAND-CONST: 9985 
11 RAND-RAND: 9939 RAND-CONST: 10057 
12 RAND-RAND: 9945 RAND-CONST: 10013 
13 RAND-RAND: 10090 RAND-CONST: 9936 
14 RAND-RAND: 10000 RAND-CONST: 9867 
15 RAND-RAND: 10055 RAND-CONST: 10088 
16 RAND-RAND: 10129 RAND-CONST: 9875 
17 RAND-RAND: 9846 RAND-CONST: 10056 
18 RAND-RAND: 9961 RAND-CONST: 9930 
19 RAND-RAND: 10063 RAND-CONST: 10001 
20 RAND-RAND: 10047 RAND-CONST: 10037 
AVG RAND-RAND: 9988.05 AVG RAND-CONST: 9986.8 

Dados los resultados anteriores diría que a todos los efectos prácticos, ambas opciones son equivalentes, dando a la espera 1/1000 resultado en ambos casos .

+2

+1, aunque tengo que responder su "Deje que los datos hablen por sí mismos" con http://www.dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/00000/2000/300/2318/2318 .strip.gif – balpha

+0

Bueno, en este caso ambos resultados son los esperados ~ 1/1000 por lo que no hay olor –

+2

Esta metodología de prueba realmente no es correcta, porque siempre llama a rand() dos veces en cada iteración. Una prueba más precisa correría un rand de prueba de bucle (1,1000) == 1000 y un rand de prueba de segundo bucle (1,1000) == rand (1,1000). –

1

La forma en que funcionan la mayoría de los generadores aleatorios, la salida no es realmente aleatoria sino que se basa en un algoritmo que debe hacer que los valores devueltos parezcan aleatorios y distribuidos. En base a eso, creo que la probabilidad real de que obtengas el mismo número dos veces seguidas es incluso menor que en el mundo real si tuvieras dos "generadores aleatorios" totalmente independientes.

Editar: Una vez dicho esto, no tengo información privilegiada sobre cómo funciona el generador aleatorio predeterminado en php.

+0

+1 para señalar la no aleatoriedad de la mayoría de los PRNG. – paxdiablo

0

La opción 1 está garantizada para ser correcta.

no creo que aprendí bastante probabilidad y estadística en su día para decir si la opción 2 es correcta.

lo hice, sin embargo, saber que uno nunca debe confiar generador de números aleatorios de otra persona sin ejecutar programas de prueba en él, para tener una idea de cómo al azar lo que realmente es.

En su caso, había corrido unos pocos millones de casos de prueba a través de ambas opciones, para ver si la opción 2 se acercó con estadísticas similares a la Opción 1.

+0

En * teoría * son lo mismo. –

-3

En teoría, sí, las dos expresiones tienen exactamente el la misma probabilidad de ser cierto Eso supone que el generador de números aleatorios de PHP es de hecho aleatorio; si no lo es, uno será más probable que el otro.

El mejor enfoque sería la de realizar un experimento (miles de iteraciones) y ver qué pasa.

+1

Ese es ciertamente * no * el mejor enfoque. La evidencia experimental solo puede dar, en el mejor de los casos, una indicación, incluso con * millones * de iteraciones. El mejor enfoque es determinista donde se examina el algoritmo. – paxdiablo

3

SI el generador de números aleatorios es verdaderamente aleatorio, ambos enfoques producen el mismo resultado. Sin embargo, los generadores de números aleatorios por computadora no son perfectos. Dudo que los defectos sean suficientes, pero la única manera de saberlo con certeza es probarlo: realizar una prueba el mayor tiempo posible y ver si hay una desviación de lo que debería ser. Necesitarás millones de números aleatorios como mínimo.

+0

+1 para tener en cuenta la no aleatoriedad de la mayoría de los generadores de números "aleatorios" basados ​​en computadora. – paxdiablo

8

Sí, rand (1,1000) = 1,000 es tan probable como rand (1,1000) = rand (1,1000).

Imagine rodando dos dados.Después de rodar el primero, ¿cuál es la probabilidad de que el segundo sea igual al primero cuando se lanza? 1/6.

Ahora anote un número entre 1 y 6 y tire un dado. ¿Cuál es la probabilidad de que los dados sean iguales a los que acabas de escribir? 1/6.

+0

Buena explicación, pero no pude asegurar si rodar un dado una vez y hacer que coincida con un número sería más probable que girarlo dos veces (o tirar dos dados) y hacer que muestre el mismo número ... – Ropstah

+0

Tengo que estar en desacuerdo con esta respuesta. Mientras que la primera oración es verdadera para eventos verdaderamente aleatorios, los generadores de números aleatorios en las computadoras generalmente no son verdaderamente aleatorios. De hecho, si usa un generador congruente lineal, es casi seguro que dos números consecutivos serían los mismos (sujetos al módulo). – paxdiablo

2

Esto no aborda directamente su pregunta, pero es posible que desee consultar mt_rand() en su lugar. La documentación de PHP:

Muchos generadores de números aleatorios de mayor edad libcs ​​tienen dudosas o desconocidas características y son lentos. Por por defecto, PHP usa el generador de números random de libc con la función rand() . La función mt_rand() es un reemplazo directo para esto. Utiliza un generador de números aleatorios con características conocidas utilizando el »Mersenne Twister, que generará números aleatorios cuatro veces más rápido que que proporciona el promedio libc rand().

De http://www.php.net/manual/en/function.mt-rand.php.

Cuestiones relacionadas