2009-08-19 14 views
5

¿Por qué esto a veces devuelve 2?Devolver número aleatorio pero no 2

function pickServer(){ 
    $varr = rand(1,4); 
    if($varr==2){ 
     pickServer(); 
    } 
    return $varr; 
} 
+0

Gracias a todos, todos correctos, pero tuve que elegir uno solo. :) – Abs

+14

En realidad, a la mayoría de ellos les falta el problema real (incluida la respuesta aceptada). No use la recursividad como un Goto. Ponga un círculo alrededor de la llamada $ var = rand (1,4) hasta que devuelva un valor! = 2, no vuelva a llamar a pickServer dentro de este método. ¡Piensa en los niños! ¡Piensa en tu Stack Frame! Si ejecuta este código y alcanza una racha de 2, podría teóricamente crear condiciones de StackOverflow y no estoy hablando de un sitio de Q & A Wiki. – JohnFx

+5

No bucle en absoluto. Su rango de generación aleatorio es demasiado grande; no lo ve porque el número que desea excluir está dentro del rango. Si fuera al principio o al final no harías loop, entonces ¿por qué loop simplemente porque está en el medio? Remapear – Nosredna

Respuesta

19

Porque no se detiene la función allí. la cuarta línea debería decir:

return pickServer(); 
+2

Esto sigue siendo recursivo y potencialmente peligroso. Vea el comentario-discusión sobre la pregunta original. –

+0

Esto es útil para responder al "por qué". Pero resulta en una solución terrible, como señala Robert. – Nosredna

2

Porque cuando el valor es 2 no devuelve pickserver. Y la función continúa devolviendo $ varr.

0

Llama a la función recursivamente para obtener otro número que no es 2, pero no hace nada con ese resultado.

Intente cambiar pickServer() a return pickServer().

Mejor aún, escribir la función iterativa para que solo un bucle hasta que el valor devuelto no es 2.

2
function pickServer(){ 
    $varr = rand(1,4); 
    if($varr==2){ 
     return pickServer(); //leave here 
    } 
    return $varr; 
} 
10

Lo que probablemente quiere es

function pickServer(){ 
    $varr = rand(1,4); 
    if($varr==2){ 
    $varr = pickServer(); 
    } 
    return $varr; 
} 

- pero tenga en cuenta que no hay no hay garantía de que esto no vaya a una recursividad demasiado larga. Tal vez debería más bien hacer algo como esto:

function pickServer(){ 
    $varr = rand(1,3); 
    if($varr > 1){ 
    $varr = $varr + 1; 
    } 
    return $varr; 
} 
+1

Funciona tan bien como el de Nosredna, pero tuvo que pensar un segundo. – OIS

+0

Su segundo código aborda bien el problema. Mi preocupación con esto es solo que es un poco difícil de descifrar. De hecho, me lo perdí cuando estaba leyendo las respuestas la primera vez hasta precisamente porque no es obvio. Me disculpo por extrañarlo. Si lo hubiera notado la primera vez, te habría acreditado en mi respuesta. – Nosredna

+0

Actualización: les di puntales en mi respuesta. – Nosredna

0

que se olvidó de devolver el valor ...

function pickServer(){ 
$varr = rand(1,4); 
if($varr==2){ 
    return pickServer(); 
} 
return $varr; 
} 
13

Otra manera de hacerlo es utilizando do … while:

function pickServer() { 
    do { 
     $varr = rand(1,4); 
    } while ($varr == 2); 
    return $varr; 
} 
+2

Podría decirse que es mejor ya que la mayoría de los lenguajes no optimizan la recursividad de cola y esto no es menos claro que el recusivo. –

+1

Finalmente, alguien con cierto sentido para señalar que el uso de la recursividad como un goto es una locura. +1 – JohnFx

+2

Creo que para el problema en cuestión, tanto la recursividad como los bucles son una locura. :-) – Nosredna

26

La respuesta a su pregunta, como han señalado otros, es que su código se cae sin regresar. Si 2 es devuelto por la llamada a rand() en el primer intento y el segundo intento (hay una probabilidad 1/16 de que esto ocurra), obtendrá 2 como resultado.

Pero su enfoque para resolver el problema podría ser mejor.

Tanto la recursividad como el bucle son molestos para este problema. Este es un problema de asignación de , no es un problema de aleatoriedad . (Se parece algo de aleatoriedad común de codificación problemas de entrevistas que pueden ser manejados con mayor facilidad en un bucle de rechazo, pero en realidad no es un problema de esa clase.)

¿Quieres uno de los tres resultados, no cuatro . (1, 3 y 4.) Eso significa que debe generar un rango de tres números aleatorios, no cuatro. Puede reasignar con una matriz o usar un if. Ambas posibilidades se muestran a continuación. Avíseme si tengo una sintaxis incorrecta: mi PHPfu es débil esta mañana.

/* array remapping */ 
function pickServer() { 
    $remap = array(1, 3, 4); 
    return $remap[rand(1,3)]; 
} 

/* if remapping */ 
function pickServer() { 
    $server = rand(1,3); 
    if ($server==2) { 
     $server=4; 
    } 
    return $server; 
} 

No me di cuenta antes, pero balpha anticipó mi respuesta. Remató con un if en su segundo ejemplo. En lugar de reasignar 2 a 4, acaba de agregar uno a cualquier respuesta por encima de 1, que es una solución equivalente.

+1

La sintaxis me parece correcta. Bien hecho. * Esta * debería haber sido la respuesta seleccionada. –

+2

Un verdadero RNG aleatorio podría devolver 2 para siempre. Al menos esto no se quedará atascado en un bucle. – OIS

+1

Creo que encontrará que un RNG verdadero siempre devuelve 4: http://imgs.xkcd.com/comics/random_number.png – nickf

1

yo por lo menos así:

function pickServer() 
{ 
$servers = array(1,3,4); 
return $servers[rand(1,count($servers))]; 
} 
+0

Pensé que se llamaba rand() con cero o dos parámetros en PHP. – Nosredna

+0

rand devuelve enteros. Creo que esto es lo que estabas buscando ... devuelve $ servers [rand (1, count ($ servers))]; – Nosredna

+0

Gracias, Nosrenda, actualicé mi código. –

0

se puede quitar la recursividad y volver a asignar un seleccionados al azar 2. limitan a disminuir el alcance y el mapa los principios de la gama (en este caso 2) a 1.

function pickServer(){ 
    $varr = rand(2,4); 
    if($varr==2){ 
     return 1; 
    } 
    return $varr; 
} 
Cuestiones relacionadas