2009-03-18 23 views
8

Quiero ejecutar una función que tenga 2 resultados diferentes, pero quiero que cada resultado sea verdaderamente el 50%. Supongo que rand (0,1) es el camino a seguir, pero tengo curiosidad si eso podría favorecer a uno sobre el otro. ¿Cuál es la mejor manera de obtener un resultado 50/50?PHP rand() ... obtener verdaderos 50/50 resultados?

Gracias.

EDIT: gracias chicos, pero no quiero que sea aleatorio, quiero que el resultado sea 101010101 y no 111001101. Tal vez debería actualizar una base de datos con el último valor de salida y luego devolver el opuesto?

EDIT2: OK Lamento que mi última edición haya sido engañosa. Solo estoy llamando a la función una vez por usuario y asignando ese valor como una cookie al usuario. Quiero que cada usuario visitante reciba un 1 o un 0 en el orden 1010101.

+1

¡Eso no es justo! : P –

+0

Mi publicación menciona esto brevemente. La aleatoriedad real puede favorecer aleatoriamente a un número, pero si en su lugar comienzas con muchos números y los barajas aleatoriamente, entonces evitarás este problema (y presentarás otros problemas). – Brian

+0

¿Podría explicar la situación en la que necesita esto para trabajar? Es posible que no requiera la intervención de la base de datos. –

Respuesta

2

dependiendo del contexto específico en el que va a utilizar este número (por ejemplo, una base por usuario, tiempo de vida de la aplicación , etc.) puede almacenarlo en varios lugares, $ _SESSION, un valor de base de datos, o si el alcance solo cubre la página actual, entonces puede guardarlo directamente en el código de esa página.

Una manera fácil de cambiar el valor es:

$val = 1 - $val; 

Para una llamada de base de datos:

UPDATE YourTable SET `next_value` = 1 - `next_value` 

etc ...

+0

Mira, creo que esta solución es bastante astuta ... pero mucho menos obvia en lo que realmente hace ... Creo que alguien que la lea se preguntaría por qué diablos se escribió este código. Y si $ val (o next_value) de alguna manera se ensuciaran, todo a partir de ese momento sería incorrecto. – Beska

+0

Sí, definitivamente estaría mejor envuelto en una función ToggleNextValue() o algo así, pero depende del desarrollador asegurarse de que no está cambiando los valores que no cambia. –

1

Según the php manual rand (0,1) es el camino a seguir. Pero todo depende de cuán bueno sea el generador de números aleatorios.

1

nada es realmente 50/50. Si quiere 50/50, realice la función para que los primeros 5 resultados sean 1 y los otros 5 sean 2, etc. etc.

rand está destinado a la generación aleatoria de números. Eso significa que puede dar 10 veces el mismo resultado en una fila, pero bueno, eso es al azar.

29

en PHP mt_rand() es un generador de números aleatorios mejorado

mt_rand(0,1); 

es suficiente y debe generar un valor bastante bueno 50/50.

cita sobre el mt_rand:

Muchos generadores de números aleatorios de libcs ​​mayores tienen características dudosas o desconocidas y son lentos. Por defecto, PHP usa el generador de números aleatorios 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 producirá números aleatorios cuatro veces más rápido que lo que ofrece el promedio libc rand().

Bill tenía un buen enlace con respecto a un ejemplo visual. No sé lo que PHP el usuario tenía allí para PHP, pero desde que se incluyó el código que tengo alojado en mi servidor (Linux con PHP 5.1.6)

10

Respuesta a la pregunta editada: Si desea mantener una proporción exacta del 50%, la aleatoriedad es lo último que desea. Para sus propósitos, probablemente solo quiera asignar a cada usuario nuevo (sin cookie detectada) un autonumero de su base de datos, luego otorgarle una página al usuario de números pares y la otra página al usuario impar (como sugirió RobS en un comentario).

if(($user_id % 2) == 0) 
    // user id is even 
else 
    // user id is odd 

Respuesta original: función rand() de PHP no es un buen generador de números pseudo-aleatorios (ver un Simple Visual Example). Yo recomendaría mt_rand() en su lugar.

2

Ambos (rand() y mt_rand()) devolver una buena/50% de probabilidad del 50%.

Aquí se muestra un ejemplo:

$array1 = array(0,0); 
$array2 = array(0,0); 

for ($x = 0; $x < 10000; $x++) { 
    $array1[mt_rand(0,1)] ++; 
    $array2[rand(0,1)] ++; 
} 

print_r($array1); 
print_r($array2); 

Resultados:

Array 1 (mt_rand): 
    [0] => 4910 
    [1] => 5090 
Array 2 (rand): 
    [0] => 4970 
    [1] => 5030 

Según la petición del autor, que quiere una distribución justa. Intente algo como esto:

$digits = 200; 
$array = array_fill(0, $digits/2, 0); 
for ($x = 0; $x < $digits/2; $x++) 
    $array[] = 1; 
shuffle($array); 

Distribución igual y suficientemente aleatoria. (Sugerido por Brian)

0

La pseudoaleatoriedad nunca puede ser verdadera aleatoriedad. Cada cálculo de números aleatorios basado en una semilla o por otros medios tiene algún nivel de pre-determinación que puede surgir o no de una manera obvia, como los mini-patrones. Lo mejor que puedes esperar es casi 50/50.

1

responsabilidad: Este es una estupidez hacer para su problema particular, pero si usted insiste en desconfiar de su generador de números aleatorios para ser distribuido de manera uniforme ...

El algoritmo clásico para la generación de AA 50/50 resultado cuando no confías en que tu generador esté distribuido de manera uniforme es el siguiente algoritmo. Tenga en cuenta que este algoritmo es más destinados a la fijación de números aleatorios de números pseudo-aleatorios y de hecho puede hacer que los resultados basados-mod peor:

  1. generar dos bits aleatorios A y B.
  2. Si A == B, Goto 1
  3. Return B

también puede garantizar la igualdad de distribución por acaba de empezar con un montón de 1s y 0s (distribuida uniformemente) y arrastrando los pies al azar ellos.

0

si lo que desea alternando 1 y 0:

$n = 0; 
$myval = ($n==1 ? $n=0 : $n=1); 
0

Si realmente quiere que vuelva el valor opuesto en cada iteración ...

function flip() { 
    static $truthiness = false; 
    $truthiness = !$truthiness; 
    return $truthiness; 
} 

que debería devolver verdadero, falso, verdadero, falso, verdadero, etc. ...

Por supuesto, esto solo funciona si el intérprete de PHP permanece en la memoria entre las llamadas.

Además, si no sabe lo que hace la palabra clave estática, consulte la entrada manual de PHP en variable scope.

+0

Correcto, pero la función solo se ejecuta una vez por usuario, cuando alguien más en un sistema diferente visita, quiero que obtengan el oppisite, cuando dije 10101 que quería decir para cada visitante. –

+0

Tendría que comprobar, pero si está utilizando mod_php o algo así como APC, * think * mantiene variables estáticas entre los usuarios. No tengo forma de probar dónde estoy ahora (utilizamos Java/C# aquí). – Powerlord

0

Este 10101010 no es aleatorio, es un patrón.
resultado = no resulta

0

Esto es en respuesta a su comentario en su post original:

Su objetivo es ver qué versión de la página genera más ventas.

Tiene más sentido mostrar aleatoriamente cada página a un visitante que voltear ABABAB para cada visitante sucesivo.

Aunque no puedo imaginar ninguna razón para un sesgo sistemático con su método, no puede descartarlo. (escenario descabellado: algunos bots de seguimiento "siguen" a los usuarios a su página, y así el usuario 1 obtiene A, bot obtiene B, usuario 2 obtiene A, bot obtiene B, etc.)

Lograr una mejor aleatoriedad es más sensato cuando haciendo un estudio como el que estás haciendo, asegurándote de que cada página se muestre exactamente el 50% del tiempo.

1

RobS tiene una buena solución en los comentarios, básicamente diciendo que cada usuario puede obtener un número secuencial, luego al usar ese número% 2, obtienes un 0 o un 1, que determinará qué página servir. Por supuesto, incluso eso no está absolutamente garantizado para dar exactamente una proporción 50/50 ... ¡podría tratarse de un número impar de personas!

Además, dependiendo de cómo determine a los usuarios, puede valer la pena verificar que no haya algún tipo de correlación que pueda dar más probabilidades de que las personas con números pares compren ... poco probable, pero algo a tener en cuenta.

Hay una solución alternativa para usted, donde no tendrá que preocuparse por extrañas correlaciones inesperadas: en función de sus comentarios y preguntas modificadas, solo está tratando de obtener una comparación de análisis justo entre la efectividad de dos páginas diferentes Los diseños son, simplemente podría dividir las ventas de diseño de página por la cantidad de veces que se sirvió al azar. es decir, utiliza su generador de números aleatorios, y realiza un seguimiento de cuántas veces da 0 para mostrar la página A, y cuántas veces da 1 para mostrar la página B.

Supongamos que gana $ 50,000 en ventas en la página a con 43 hits, y $ 46.000 en ventas en la página B con 38 golpes, sólo tiene que hacer los cálculos ...

Page A      Page B 

50000      46000 
----- = 1163 $/hit   ----- = 1211 $/hit 
    43       38 

Dando la página B ligera ventaja.

Cuestiones relacionadas