Usar la hora del sistema directamente para obtener números aleatorios

Tuve que devolver un elemento aleatorio de una matriz, así que se me ocurrió este marcador de posición:

return codes[(int) (System.currentTimeMillis() % codes.length - 1)];

Ahora que lo pienso, estoy tentado a usarlo en código real. La Random() seeder usa el tiempo del sistema como semilla en la mayoría de los idiomas de todos modos, así que ¿por qué no usar ese tiempo directamente? Como beneficio adicional, estoy libre de la preocupación de los bits inferiores no aleatorios de muchos RNG. ¿Es este truco volviendo a morderme? (El lenguaje es Java si eso es relevante).

preguntado el 08 de enero de 11 a las 20:01

4 Respuestas

Utilice el java.util.Random integrado. Ítem ​​47 de Java eficaz (segunda edición, página 215) presenta esto como un ejemplo de por qué debería preferir las bibliotecas estándar a las suyas propias. Comienza explicando que Math.abs(rnd.nextInt() % n es un mal enfoque, ya que no produce una distribución verdaderamente aleatoria y que simplemente debería usar rnd.nextInt(n) en lugar de. Continúa diciendo:

Para escribir una versión del random que corrige estos tres flays, tendrías que saber bastante sobre generadores de números pseudoaleatorios, teoría de números y aritmética en complemento a dos.

...

No tiene que preocuparse por los detalles de cómo nextInt(int) hace su trabajo. Un ingeniero senior con experiencia en algoritmos pasó mucho tiempo diseñando, implementando y probando este método y luego lo mostró a varios expertos en el campo para asegurarse de que fuera correcto. Luego, la biblioteca fue probada en versión beta, lanzada y utilizada ampliamente por millones de programadores durante la mayor parte de una década. Aún no se han encontrado fallas en el método, pero si se descubriera una falla, se solucionaría en el próximo lanzamiento. Al utilizar una biblioteca estándar, aprovecha el conocimiento de los expertos que la escribieron y la experiencia de quienes la utilizaron antes que usted.

Cabe señalar que aunque el ejemplo no usa exactamente el mismo código que el que está sugiriendo, es aún más cierto para su ejemplo. Tomar el resto de un entero aleatorio sesga la distribución, pero al menos tiene cierta apariencia de aleatoriedad. Modificar la hora es un enfoque aún peor.

Subestimas la complejidad de los generadores de números pseudoaleatorios. El problema con el enfoque que está sugiriendo es que no solo es posible que la distribución esté lejos de ser aleatoria, sino que, además, será realmente predecible. Hay ejemplos reales de piratas informáticos que explotan generadores de números pseudoaleatorios con semillas predecibles para hacer trampa en el póquer. Construyendo software seguro (Viega y McGraw, 2002) contiene un capítulo completo que discute estos temas.

Este es un buen ejemplo de cómo los PRNG deficientes pueden romperse en la práctica. En 1999, el Grupo de Seguridad de Software en Cigital descubrió una falla seria en la implementación de Texas Hold 'em Poker, que es distribuido por ASF Software, Inc. El exploit permitió a un jugador que hacía trampa calcular el mazo exacto que se usaba para cada mano en reales. hora. Esto significa que un jugador que usa el exploit conoce las cartas en la mano de cada oponente, así como las cartas que componen el flop (cartas colocadas boca arriba en la mesa después de las rondas de apuestas). Un tramposo puede "saber cuándo retenerlos y cuándo doblarlos" cada vez. Un atacante malintencionado podría usar el exploit para estafar a jugadores inocentes con dinero real sin que todos los atrapen. (Página 238)

Aquí hay dos preguntas que analizan la complejidad de la aleatoriedad:

Este es un artículo que tiene solo unas pocas semanas (pero con un título muy poco convincente) que describe cómo podría atacar el algoritmo de generación de sesiones de PHP utilizando la semilla predecible del PRNG:

contestado el 23 de mayo de 17 a las 15:05

¡Es una idea terrible! ¡Ni lo pienses! Las llamadas sucesivas a este 'generador de números pseudoaleatorios' de cosecha propia se correlacionarán tan fuertemente que bien podría estar usando un simple contador. (Que, en caso de que te lo hayas perdido, no lo recomiendo).

Editado para agregar: Por cierto, como lo ha codificado, su índice de matriz ocasionalmente será -1. Esta también es una idea terrible.

Respondido el 09 de enero de 11 a las 00:01

La única razón por la que puedo pensar en contra de esto es: ¿Qué pasa si el reloj del sistema siempre devuelve un múltiplo de 16 (esto puede suceder en máquinas con Windows XP, por ejemplo), y su matriz tiene una longitud de 16?

Respondido el 08 de enero de 11 a las 23:01

En general, existen buenas razones para que las clases de biblioteca estándar se hayan desarrollado en primer lugar.

Si bien puede ser interesante experimentar con la escritura de su propio código para abordar problemas en un entorno académico, en un entorno empresarial es mejor utilizar bibliotecas y técnicas probadas y comprobadas que tienen menos probabilidades de crear comportamientos no deseados en su aplicación.

Si está decidido a utilizar su técnica, le sugiero encarecidamente que escriba casos de prueba exhaustivos para probar las condiciones de contorno y un gran conjunto de puntos de datos. Esto le ayudará a depurar su código antes de que llegue a producción.

Respondido el 08 de enero de 11 a las 23:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.