2010-06-17 11 views
15

Solo por curiosidad, ¿Math.random() puede ser cero?¿La función aleatoria de Java puede ser cero?

Por ejemplo, si tuviera que tener:

while (true){ 
    if (Math.random() == 0) 
    return 1; 
} 

Podría yo realmente obtener un retorno de uno? También hay un error de redondeo para tener en cuenta porque Math.random() devuelve un doble.

Pregunto porque mi profesor de CS declaró que al azar() va de 0 a 1 inclusive, y siempre pensé que era exclusivo.

+5

¿Estaba su profesor de CS hablando de Java, o más bien acerca de una función aleatoria puramente matemática con igual distribución? Debido a que dicha función, para el rango de los números reales de 0 a 1, no tiene ninguna probabilidad de 0. Tampoco para 1. Ni para 0.5: la probabilidad A solo puede asignarse a un intervalo. Pero eso por supuesto no es cierto para un rango de números discretos como lo tenemos aquí en Java ... (Estoy seguro, eso es lo que quiso decir;) –

+0

Solo revisa la documentación de Math.random(), indicará si es inclusiva o exclusivo –

+0

No hay error de redondeo aquí, por cierto.Obtendrás un 'doble' con 53 bits pseudoaleatorios distribuidos uniformemente en su mantisa. – Joey

Respuesta

21

De acuerdo con the documentation, "Devuelve un valor doble con un signo positivo, mayor o igual que 0.0 y menor que 1.0." Esto significa que puede ser cero.

Como Hank wrote, que es exclusiva en el límite superior (nunca puede ser 1), así que tal vez ahí es donde tu confusión proviene de :-).

9

Incluye el cero, exclusivo de uno, por ejemplo, [0, 1) o 0 <= x < 1 según la notación que prefiera.

1

Math.random() es documented volver "un valor doble con un signo positivo, mayor que o igual a 0,0 y menos de 1,0" Esto es, inclusive de 0,0 pero exclusivo de 1,0

5

En teoría , puede devolver el valor cero.

En la práctica, es posible que tenga que esperar un tiempo extremadamente largo para obtener exactamente cero. Si el generador de números aleatorios se implementa bien, tiene al menos 56 bits de estado interno (de lo contrario, todos los bits del resultado devuelto no serán aleatorios). Y eso implica, si la distribución de los valores producidos por el azar es plana, que tiene como máximo una posibilidad en 2^56 de recuperar un valor cuyos bits son cero. Eso es aproximadamente 10^-19. No aguantaría la respiración.

(Otros han observado con razón que, como está documentado, en teoría [y presumiblemente en la práctica] no puede devolver el valor 1.0).

+0

Puede hacer el mismo caso para cualquier combinación de los 56 bits del estado interno. Si el generador de números aleatorios se implementa bien, la posibilidad de devolver cero debería ser la misma que cualquier otro doble discreto. –

+0

@Gilbert: De acuerdo, pero la pregunta era específicamente "¿puede ser cero?" –

+0

Java usa un LCG de 48 bits del que solo se utilizan 32 bits. Esto también se observa en la documentación para 'nextLong()' que simplemente * no * puede generar todos los valores posibles 'largos'. Lo mismo ocurre (obviamente) para 'double's. – Joey

1

también es posible, en una aplicación compatible con JRE, que nunca devuelve 0.

+2

también es posible, dado un generador verdaderamente aleatorio y debido a la naturaleza de la aleatoriedad que, en una implementación de JRE compatible, SIEMPRE devuelve 0. –

+0

@Stephen: Lee los Javadocs (que, para la biblioteca estándar, se consideran parte del especificación). Cualquier implementación de 'Math.random()' * tiene que * usar 'java.util.Random' que a su vez * tiene que ser * un LCG específico. – Joey

+0

@Johannes: Leo los javadocs y los relacioné en mi respuesta. Lo que quiero decir, en relación con la respuesta irrebatible, es que si bien es * posible * que nunca se devuelve 0.0, también es posible que se devuelva * siempre * 0.0. Para cumplir, debe ser posible que se devuelva cualquier valor * x * donde se devuelva 0.0 <= * x * <1.0, incluidos los casos improbables en los que 0 nunca se devuelve o 0 siempre se devuelve. Primero leí la afirmación de irrecuperable como "podría escribir un JRE compatible que nunca devolvería 0." lo cual está mal, pero el caso * improbable * de que 0 nunca se devuelve * es * correcto. –

10

Es perfectamente posible que nunca volverá exactamente cero.El PRNG incluido de Java es un LCG de 48 bits del que solo se utilizan 32 bits. Para que los 53 bits de una mantisa double sean cero, básicamente necesitará al menos una llamada aldonde los 32 bits superiores son cero y el otro donde están la mayoría de ellos. (Si no me equivoco, diría que esto nunca sucederá con el funcionamiento del generador, pero es tarde, estoy cansado y no apostaría mucho).

Dado que el La documentación del método establece explícitamente cómo se obtienen los números aleatorios, también hay poco margen para que otras implementaciones del tiempo de ejecución de Java arrojen resultados diferentes. El contrato podría decir que el número que obtiene es de [0, 1). Pero en la práctica hay una cantidad considerable de valores que nunca alcanzará (porque necesita dos valores sucesivos de un generador que produzca forzosamente una dependencia lineal entre valores sucesivos; solo hay 48 bits de estado. No puede generar todos los valores diferentes). Combinaciones de 53 bits de eso, al menos no cómo se hace).

Por supuesto, ya Math.random() semillas automáticamente una instancia estática Random, también podríamos tener que considerar aquí la semilla, que puede necesidad de ser muy específico para un caso de prueba para hacer ejercicio. Y eso podría significar que ese punto exacto en el tiempo podría estar a unas pocas décadas o milenios de distancia.

+0

+1 Siempre me he preguntado si alguna vez obtendría un cero .... – mikera

+0

Como contraejemplo práctico, Angs '[respuesta a continuación] (http://stackoverflow.com/a/4371484/733345) muestra un estado de PRNG específico donde el generador devolverá exactamente esa combinación de 'next()' s. – Joe

35

Sí, es realmente puede ser. Math.random() crea un generador global java.util.Random con semilla (System.currentTimeMillis()^0x5DEECE66DL) & ((1L << 48) - 1) y llama al nextDouble() para ello. Si su semilla alcanza el estado 107048004364969L (y lo hará, dado que java.util.Random tiene un período completo), el siguiente double generado será 0.0. Aunque con mala suerte podría terminar con la paridad incorrecta en el ciclo, porque Random.nextDouble() avanza el estado dos veces. Con un poco menos de mala suerte, podrías generar 2^47 números aleatorios antes de que termine el ciclo, ya que no encontré otras semillas que den 0.0.

La semilla avanza como si fuera seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); y los dobles se generan usando 26 y 27 bits superiores de dos valores de inicialización consecutivos. En el ejemplo, los dos valores de inicialización siguientes serán 0L y 11L.

Si logra crear el generador global con System.currentTimeMillis()==107038380838084L, su código regresa inmediatamente. Se puede simular esto con:

java.util.Random k = new java.util.Random(107038380838084L); System.out.println(k.nextDouble()==0);

+8

Y, si crees que parece demasiado sospechoso llegar a cero en el próximo intento, usa 'new java.util.Random (164311266871034L)', y lo golpearás en dos intentos. O 'nuevo java.util.Random (240144965573432L)', y tres intentos. O 'nuevo java.util.Random (881498)', y obtendrá un cero después de las llamadas 376050 a 'nextDouble'. – cayhorstmann

+0

Esta debería ser la respuesta aceptada. La pregunta pide 'Math.random' de Java que (cuando se llama por primera vez) crea un nuevo generador de números pseudoaleatorios, exactamente como si tuviera la expresión' new java.util.Random() ', que a su vez se usa como' Random .nextDouble() 'a partir de entonces para todas las llamadas a' Math.random() '. 'nextDouble()' funciona como: 'return (((long) next (26) << 27) + next (27))/(double) (1L << 53);' (y incorrectamente en las primeras versiones de java como : 'return (((long) next (27) << 27) + next (27))/(double) (1L << 54);'). Aquí 'next' devuelve los bits superiores solicitados' (int) (seed >>> (48 - bits)) '. – GitaarLAB

1

Es teóricamente posible que math.random() para devolver un valor de cero, pero en el mundo real, puede contar con que casi nunca ocurre.

Una vez funcioné mi PC durante una semana consecutiva esperando una, generó aproximadamente 10 billones de números aleatorios, sin ceros.

Pero más directamente, es prácticamente exclusivo en ambos sentidos.

+0

No teóricamente posible, pero completamente posible. Vea la respuesta provista por @Angs y los comentarios. –

+0

Lo ejecuté durante un mes una vez, nunca obtuve un cero. – Guus

Cuestiones relacionadas