math language-agnostic random

math - Entendiendo la "aleatoriedad"



language-agnostic random (28)

No puedo entender esto, que es más aleatorio?

rand()

O

rand() * rand()

Me parece un verdadero desafío para la mente, ¿podrías ayudarme?

EDITAR:

Intuitivamente, sé que la respuesta matemática será que son igualmente aleatorias, pero no puedo evitar pensar que si "ejecuta el algoritmo de números aleatorios" dos veces cuando multiplica los dos, creará algo más aleatorio que simplemente haciendo una vez


Solo una aclaración

Aunque las respuestas anteriores son correctas cuando intenta detectar la aleatoriedad de una variable pseudoaleatoria o su multiplicación, debe tener en cuenta que aunque Random () se distribuye de manera uniforme, Random () * Random () no lo está.

Ejemplo

Esta es una muestra de distribución aleatoria uniforme simulada a través de una variable pseudoaleatoria:

BarChart[BinCounts[RandomReal[{0, 1}, 50000], 0.01]]

Si bien esta es la distribución que obtienes después de multiplicar dos variables aleatorias:

BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] * RandomReal[{0, 1}, 50000], {50000}], 0.01]]

Entonces, ambos son "aleatorios", pero su distribución es muy diferente.

Otro ejemplo

Mientras que 2 * Random () se distribuye uniformemente:

BarChart[BinCounts[2 * RandomReal[{0, 1}, 50000], 0.01]]

Aleatorio () + Aleatorio () no lo es!

BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000], {50000}], 0.01]]

El teorema del límite central

El teorema del límite central establece que la suma de Random () tiende a una distribución normal a medida que aumentan los términos.

Con solo cuatro términos obtienes:

BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000] + Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000], {50000}], 0.01]]

Y aquí puede ver el camino de una distribución uniforme a una normal al sumar 1, 2, 4, 6, 10 y 20 variables aleatorias distribuidas uniformemente:

Editar

Unos créditos

Gracias a Thomas Ahle por señalar en los comentarios que las distribuciones de probabilidad mostradas en las dos últimas imágenes se conocen como la distribución de Irwin-Hall.

Gracias a Heike por su maravillosa función desgarrada []


  1. No hay tal cosa más aleatoria. Es aleatorio o no. Aleatorio significa "difícil de predecir". No significa no determinista. Tanto random () como random () * random () son igualmente aleatorios si random () es aleatorio. La distribución es irrelevante en cuanto a la aleatoriedad. Si se produce una distribución no uniforme, solo significa que algunos valores son más probables que otros; Todavía son impredecibles.

  2. Dado que se trata de pseudoaleatoriedad, los números son muy deterministas. Sin embargo, la pseudoaleatoriedad suele ser suficiente en los modelos de probabilidad y simulaciones. Es bien sabido que hacer que un generador de números pseudoaleatorios sea complicado solo hace que sea difícil de analizar. Es poco probable que mejore la aleatoriedad; A menudo hace que falle las pruebas estadísticas.

  3. Las propiedades deseadas de los números aleatorios son importantes: repetibilidad y reproducibilidad, aleatoriedad estadística, (por lo general) distribuidas uniformemente, y un gran período son algunas.

  4. Con respecto a las transformaciones en números aleatorios: como dijo alguien, la suma de dos o más distribuidos uniformemente resulta en una distribución normal. Este es el teorema aditivo del límite central. Se aplica independientemente de la distribución de origen siempre que todas las distribuciones sean independientes e idénticas. El multiplicativoEl teorema del límite central dice que el producto de dos o más variables aleatorias independientes y distribuidas indentalmente es lognormal. El gráfico que otra persona creó parece exponencial, pero en realidad es lognormal. Entonces random () * random () se distribuye lognormalmente (aunque puede que no sea independiente ya que los números se extraen de la misma secuencia) Esto puede ser deseable en algunas aplicaciones. Sin embargo, generalmente es mejor generar un número aleatorio y transformarlo en un número lognormalmente distribuido. Aleatorio () * aleatorio () puede ser difícil de analizar.

Para más información, consulte mi libro en www.performorama.org. El libro está en construcción, pero el material relevante está ahí. Tenga en cuenta que los números de capítulo y sección pueden cambiar con el tiempo. Capítulo 8 (teoría de la probabilidad) - secciones 8.3.1 y 8.3.3, capítulo 10 (números aleatorios).


"aleatorio" frente a "más aleatorio" es un poco como preguntar qué cero es más cero.

En este caso, rand es un PRNG, por lo que no es totalmente aleatorio. (De hecho, bastante predecible si se conoce la semilla). Multiplicarlo por otro valor no lo hace más o menos aleatorio.

Un verdadero RNG de tipo criptográfico será en realidad aleatorio. Y la ejecución de valores a través de cualquier tipo de función no puede agregarle más entropía, y es muy probable que elimine la entropía, por lo que no es más aleatoria.


Algunas cosas sobre la "aleatoriedad" son contraintuitivas.

Suponiendo una distribución plana de rand() , lo siguiente le proporcionará distribuciones no planas:

  • alto sesgo: sqrt(rand(range^2))
  • sesgo de pico en el medio: (rand(range) + rand(range))/2
  • bajo: sesgo: range - sqrt(rand(range^2))

Hay muchas otras formas de crear curvas de sesgo específicas. Hice una prueba rápida de rand() * rand() y obtienes una distribución muy no lineal.


Aquí hay una respuesta simple. Considerar el monopolio. Tiras dos dados de seis caras (o 2d6 para aquellos de ustedes que prefieren la notación de juego) y toman su suma. El resultado más común es 7 porque hay 6 formas posibles de sacar un 7 (1,6 2,5 3,4 4,3 5,2 y 6,1). Mientras que un 2 solo se puede tirar en 1,1. Es fácil ver que rodar 2d6 es diferente a rodar 1d12, incluso si el rango es el mismo (ignorando que puede obtener un 1 en 1d12, el punto sigue siendo el mismo). Multiplicar sus resultados en lugar de agregarlos los va a sesgar de una manera similar, con la mayoría de sus resultados en la mitad del rango. Si está tratando de reducir los valores atípicos, este es un buen método, pero no ayudará a hacer una distribución uniforme.

(Y, por extraño que parezca, también aumentarán las tiradas bajas. Suponiendo que su aleatoriedad comience en 0, verá un pico en 0 porque girará lo que sea la otra tirada en 0. Considere dos números aleatorios entre 0 y 1 (inclusive ) y multiplicando. Si cualquiera de los resultados es un 0, todo se convierte en un 0 sin importar el otro resultado. La única forma de obtener un 1 es que ambas tiradas sean un 1. En la práctica, probablemente esto no importe pero lo hace para un gráfico extraño.)


Como han dicho otros, la respuesta breve y sencilla es: No, no es más aleatorio, pero sí cambia la distribución.

Supongamos que estabas jugando un juego de dados. Tienes unos dados completamente justos, al azar. ¿Las tiradas de dados serían "más aleatorias" si antes de cada tirada, primero pusieras dos dados en un tazón, lo agitaste, escogieras uno de los dados al azar y luego tiraras ese? Claramente no haría ninguna diferencia. Si ambos dados dan números aleatorios, entonces elegir aleatoriamente uno de los dos dados no hará ninguna diferencia. De cualquier manera, obtendrá un número aleatorio entre 1 y 6 con una distribución uniforme sobre un número suficiente de tiradas.

Supongo que en la vida real tal procedimiento podría ser útil si usted sospechara que los dados NO podrían ser justos. Si, por ejemplo, los dados están ligeramente desequilibrados, por lo que uno tiende a dar 1 con más frecuencia que 1/6 del tiempo, y otro tiende a dar 6 de forma inusualmente frecuente, entonces elegir al azar entre los dos tenderá a ocultar el sesgo. (Aunque en este caso, 1 y 6 aún aparecerían más de 2, 3, 4 y 5. Bueno, supongo que dependiendo de la naturaleza del desequilibrio).

Hay muchas definiciones de aleatoriedad. Una definición de una serie aleatoria es que es una serie de números producidos por un proceso aleatorio. Según esta definición, si saco un dado justo 5 veces y obtengo los números 2, 4, 3, 2, 5, eso es una serie aleatoria. Si luego saco ese mismo dado 5 veces más y obtengo 1, 1, 1, 1, 1, entonces eso también es una serie aleatoria.

Varios carteles han señalado que las funciones aleatorias en una computadora no son realmente aleatorias sino pseudoaleatorias, y que si conoces el algoritmo y la semilla son completamente predecibles. Esto es cierto, pero la mayor parte del tiempo es completamente irrelevante. Si mezclo un mazo de cartas y luego las vuelvo de una en una, esta debe ser una serie aleatoria. Si alguien mira las cartas, el resultado será completamente predecible, pero para la mayoría de las definiciones de aleatoriedad, esto no lo hará menos aleatorio. Si la serie pasa pruebas estadísticas de aleatoriedad, el hecho de que eché un vistazo a las cartas no cambiará ese hecho. En la práctica, si estamos apostando grandes sumas de dinero en su capacidad para adivinar la próxima carta, entonces el hecho de que usted echó un vistazo a las cartas es muy relevante. Si estamos utilizando la serie para simular las selecciones de menú de los visitantes a nuestro sitio web para probar el rendimiento del sistema, entonces el hecho de que usted haya echado un vistazo no hará ninguna diferencia. (Siempre y cuando no modifique el programa para aprovechar este conocimiento).

EDITAR

No creo que pueda mi respuesta al problema de Monty Hall en un comentario, así que actualizaré mi respuesta.

Para aquellos que no leyeron el enlace de Belisario, la esencia de esto es: un concursante de un programa de juegos tiene una opción de 3 puertas. Detrás de uno hay un premio valioso, detrás de los demás algo sin valor. Él escoge la puerta # 1. Antes de revelar si es un ganador o un perdedor, el anfitrión abre la puerta # 3 para revelar que es un perdedor. Luego le da al concursante la oportunidad de cambiar a la puerta # 2. ¿Debería el concursante hacer esto o no?

La respuesta, que ofende a la intuición de muchas personas, es que él debería cambiar. La probabilidad de que su selección original haya sido el ganador es 1/3, que la otra puerta es el ganador es 2/3. Mi intuición inicial, junto con la de muchas otras personas, es que no habría ganancia en el cambio, que las probabilidades acaban de cambiarse a 50:50.

Después de todo, supongamos que alguien encendió el televisor justo después de que el anfitrión abriera la puerta perdedora. Esa persona vería dos puertas cerradas restantes. Suponiendo que conoce la naturaleza del juego, diría que hay una posibilidad de 1/2 de que cada puerta oculte el premio. ¿Cómo pueden las probabilidades para el espectador ser 1/2: 1/2 mientras que las probabilidades para el participante son 1/3: 2/3?

Realmente tuve que pensar en esto para poner mi intuición en forma. Para controlarlo, entienda que cuando hablamos de probabilidades en un problema como este, nos referimos a la probabilidad que asigna dada la información disponible. Para un miembro de la tripulación que puso el premio detrás, por ejemplo, la puerta # 1, la probabilidad de que el premio esté detrás de la puerta # 1 es del 100% y la probabilidad de que esté detrás de cualquiera de las otras dos puertas es cero.

Las probabilidades del miembro de la tripulación son diferentes a las probabilidades del participante porque sabe algo que el participante no sabe, a saber, en qué puerta dejó el premio. Del mismo modo, las probabilidades del competidor son diferentes a las probabilidades del espectador porque él sabe algo que el espectador no sabe, a saber, qué puerta eligió inicialmente. Esto no es irrelevante, porque la elección del anfitrión de qué puerta abrir no es aleatoria. No abrirá la puerta que eligió el participante, y no abrirá la puerta que oculta el premio. Si estas son la misma puerta, eso le deja dos opciones. Si son puertas diferentes, solo queda una.

Entonces, ¿cómo se nos ocurre 1/3 y 2/3? Cuando el participante originalmente escogió una puerta, tenía un 1/3 de probabilidad de elegir al ganador. Creo que mucho es obvio. Eso significa que hubo una probabilidad de 2/3 de que una de las otras puertas es la ganadora. Si el anfitrión le da la oportunidad de cambiar sin dar ninguna información adicional, no habrá ganancia. De nuevo, esto debería ser obvio. Pero una forma de verlo es decir que hay una posibilidad de 2/3 de que gane al cambiar. Pero tiene 2 alternativas. Así que cada uno tiene solo 2/3 dividido por 2 = 1/3 de probabilidad de ser el ganador, lo cual no es mejor que su selección original. Por supuesto que ya sabíamos el resultado final, esto solo lo calcula de una manera diferente.

Pero ahora el anfitrión revela que una de esas dos opciones no es la ganadora. Entonces, de la posibilidad de 2/3 de que una puerta que no eligió sea la ganadora, ahora sabe que 1 de las 2 alternativas no lo es. El otro puede o no puede ser. Entonces ya no tiene 2/3 dividido por 2. Tiene cero para la puerta abierta y 2/3 para la puerta cerrada.


El concepto que busca es "entropía", el "grado" de desorden de una cadena de bits. La idea es más fácil de entender en términos del concepto de "máxima entropía".

Una definición aproximada de una cadena de bits con máxima entropía es que no se puede expresar exactamente en términos de una cadena de bits más corta (es decir, usar algún algoritmo para expandir la cadena más pequeña de vuelta a la cadena original).

La relevancia de la máxima entropía para la aleatoriedad se deriva del hecho de que si selecciona un número "al azar", es casi seguro que elija un número cuya cadena de bits esté cerca de tener la máxima entropía, es decir, no se puede comprimir. Esta es nuestra mejor comprensión de lo que caracteriza a un número "aleatorio".

Por lo tanto, si desea hacer un número aleatorio de dos muestras aleatorias que es "dos veces" como aleatorio, debe concatenar las dos cadenas de bits juntas. En la práctica, simplemente se rellenan las muestras en las mitades altas y bajas de una palabra de doble longitud.

En una nota más práctica, si se encuentra cargado con un rand de mierda (), a veces puede ayudar a juntar un par de muestras, aunque, si está realmente roto, incluso ese procedimiento no ayudará.


El obligatorio xkcd ...


La mayoría de las implementaciones de rand () tienen algún período. Es decir, después de un número enorme de llamadas, la secuencia se repite. La secuencia de salidas de rand() * rand() repite en la mitad del tiempo, por lo que es "menos aleatoria" en ese sentido.

Además, sin una construcción cuidadosa, realizar aritmética en valores aleatorios tiende a causar menos aleatoriedad. Un cartel arriba citó " rand() + rand() + rand() ..." (k veces, digamos) que en realidad tenderá a k veces el valor medio del rango de valores que devuelve rand() . (Es un paseo aleatorio con pasos simétricos sobre esa media).

Supongamos, concretamente, que su función rand () devuelve un número real aleatorio distribuido uniformemente en el rango [0,1). (Sí, este ejemplo permite una precisión infinita. Esto no cambiará el resultado). No seleccionó un idioma en particular y los diferentes idiomas pueden hacer cosas diferentes, pero el siguiente análisis se sostiene con modificaciones para cualquier implementación no perversa de rand ( ). El producto rand() * rand() también está en el rango [0,1) pero ya no se distribuye uniformemente. De hecho, es probable que el producto esté en el intervalo [0,1 / 4) que en el intervalo [1 / 4,1). Más multiplicación sesgará el resultado aún más hacia cero. Esto hace que el resultado sea más predecible. A grandes rasgos, más predecible == menos aleatorio.

Casi cualquier secuencia de operaciones en una entrada aleatoria uniforme no será uniformemente aleatoria, lo que conducirá a una mayor previsibilidad. Con cuidado, uno puede superar esta propiedad, pero luego hubiera sido más fácil generar un número aleatorio distribuido uniformemente en el rango que realmente deseaba en lugar de perder tiempo con la aritmética.


La respuesta aceptada es bastante hermosa, pero hay otra forma de responder a tu pregunta. La respuesta de PachydermPuncher ya tiene este enfoque alternativo, y voy a ampliarlo un poco.

La forma más fácil de pensar acerca de la teoría de la información es en términos de la unidad de información más pequeña, un solo bit.

En la biblioteca estándar de C, rand() devuelve un número entero en el rango de 0 a RAND_MAX , un límite que puede definirse de manera diferente según la plataforma. Supongamos que RAND_MAX se define como 2^n - 1 donde n es algún número entero (esto sucede en la implementación de Microsoft, donde n es 15). Entonces diríamos que una buena implementación devolvería n bits de información.

Imagina que rand() construye números aleatorios lanzando una moneda para encontrar el valor de un bit y luego repitiendo hasta que tenga un lote de 15 bits. Entonces los bits son independientes (el valor de cualquier bit no influye en la probabilidad de que otros bits en el mismo lote tengan un cierto valor). Por lo tanto, cada bit considerado independientemente es como un número aleatorio entre 0 y 1 inclusive, y está "distribuido uniformemente" en ese rango (es probable que sea 0 como 1).

La independencia de los bits garantiza que los números representados por lotes de bits también se distribuirán uniformemente en su rango. Esto es intuitivamente obvio: si hay 15 bits, el rango permitido es cero a 2^15 - 1 = 32767. Cada número en ese rango es un patrón único de bits, como:

010110101110010

y si los bits son independientes, entonces no es más probable que ocurra un patrón que cualquier otro patrón. Así que todos los números posibles en el rango son igualmente probables. Y así ocurre lo contrario: si rand() produce enteros distribuidos uniformemente, esos números están hechos de bits independientes.

Así que piense en rand() como una línea de producción para hacer bits, lo que resulta que los sirve en lotes de tamaño arbitrario. Si no le gusta el tamaño, divida los lotes en bits individuales y luego vuelva a juntarlos en las cantidades que desee (aunque si necesita un rango en particular que no sea una potencia de 2, debe reducir sus números) , y por mucho, la forma más fácil de hacerlo es convertir a punto flotante).

Volviendo a su sugerencia original, suponga que desea pasar de lotes de 15 a lotes de 30, solicite a rand() el primer número, modifíquelo en 15 lugares, luego agregue otro rand() a él. Esa es una manera de combinar dos llamadas a rand() sin alterar una distribución uniforme. Funciona simplemente porque no hay superposición entre las ubicaciones donde coloca los bits de información.

Esto es muy diferente de "estirar" el rango de rand() multiplicando por una constante. Por ejemplo, si desea duplicar el rango de rand() , puede multiplicar por dos, pero ahora solo obtendrá números pares y nunca números impares. Esa no es exactamente una distribución uniforme y podría ser un problema grave dependiendo de la aplicación, por ejemplo, un juego parecido a una ruleta que supuestamente permite apuestas par / impar. (Al pensar en términos de bits, evitaría ese error intuitivamente, porque se daría cuenta de que multiplicar por dos es lo mismo que desplazar los bits hacia la izquierda (mayor significado) en un lugar y llenar el espacio con cero. Entonces, obviamente, la cantidad de información es la misma, simplemente se movió un poco.)

Dichas brechas en los rangos numéricos no se pueden controlar en aplicaciones de números de punto flotante, porque los rangos de punto flotante tienen brechas en ellos que simplemente no se pueden representar en absoluto: existe un número infinito de números reales faltantes en la brecha entre cada dos flotantes representables números de punto! Entonces solo tenemos que aprender a vivir con brechas.

Como otros han advertido, la intuición es arriesgada en esta área, especialmente porque los matemáticos no pueden resistir el encanto de los números reales, que son cosas terriblemente confusas llenas de infinitos y paradojas aparentes.

Pero al menos si piensas en términos de bits, tu intuición podría llevarte un poco más lejos. Los bits son realmente fáciles, incluso las computadoras pueden entenderlos.


Podría ayudar a pensar en esto en números más discretos. Considera la posibilidad de generar números aleatorios entre 1 y 36, por lo que decides que la forma más fácil es lanzar dos dados justos de 6 caras. Usted obtiene esto:

1 2 3 4 5 6 ----------------------------- 1| 1 2 3 4 5 6 2| 2 4 6 8 10 12 3| 3 6 9 12 15 18 4| 4 8 12 16 20 24 5| 5 10 15 20 25 30 6| 6 12 18 24 30 36

Tenemos 36 números, pero no todos están representados de manera justa, y algunos no ocurren en absoluto. Los números cerca de la diagonal central (esquina inferior izquierda a esquina superior derecha) aparecerán con la frecuencia más alta.

Los mismos principios que describen la distribución injusta entre los dados se aplican igualmente a los números de punto flotante entre 0.0 y 1.0.


Supongo que ambos métodos son aleatorios, aunque mi sensación de gut diría que rand() * rand() es menos aleatorio porque generaría más ceros. Tan pronto como un rand() es 0 , el total se convierte en 0


Tampoco es ''más aleatorio''.

rand() genera un conjunto predecible de números basado en una semilla pseudoaleatoria (generalmente basada en la hora actual, que siempre está cambiando). Multiplicar dos números consecutivos en la secuencia genera una secuencia de números diferente, pero igualmente predecible.

Si se aborda si esto reducirá las colisiones, la respuesta es no. En realidad aumentará las colisiones debido al efecto de multiplicar dos números donde 0 < n < 1 . El resultado será una fracción más pequeña, lo que provocará un sesgo en el resultado hacia el extremo inferior del espectro.

Algunas explicaciones adicionales. En lo siguiente, "impredecible" y "aleatorio" se refieren a la capacidad de alguien para adivinar cuál será el próximo número en función de los números anteriores, es decir. un oráculo

Dada la semilla x que genera la siguiente lista de valores:

0.3, 0.6, 0.2, 0.4, 0.8, 0.1, 0.7, 0.3, ...

rand() generará la lista anterior, y rand() * rand() generará:

0.18, 0.08, 0.08, 0.21, ...

Ambos métodos siempre producirán la misma lista de números para la misma semilla, y por lo tanto son igualmente predecibles por un oráculo. Pero si observa los resultados para multiplicar las dos llamadas, verá que todas están por debajo de 0.3 pesar de una distribución decente en la secuencia original. Los números están sesgados debido al efecto de multiplicar dos fracciones. El número resultante siempre es más pequeño, por lo tanto, es mucho más probable que sea una colisión a pesar de ser igual de impredecible.


Exceso de simplificación para ilustrar un punto.

Supongamos que su función aleatoria solo genera 0 o 1 .

random() es uno de (0,1) , pero random()*random() es uno de (0,0,0,1)

Puede ver claramente que las posibilidades de obtener un 0 en el segundo caso no son iguales a las de obtener un 1 .

Cuando publiqué esta respuesta por primera vez, quería mantenerla lo más breve posible para que la persona que la lea entienda de un vistazo la diferencia entre random() y random()*random() , pero no puedo evitar responder. La pregunta original de litteram:

¿Cuál es más aleatorio?

Siendo random() , random()*random() , random()+random() , (random()+1)/2 o cualquier otra combinación que no lleve a un resultado fijo tiene la misma fuente de entropía (o el mismo estado inicial en el caso de generadores pseudoaleatorios), la respuesta sería que son igualmente aleatorios (la diferencia está en su distribución). Un ejemplo perfecto que podemos ver es el juego de Craps. El número que obtengas sería random(1,6)+random(1,6) y todos sabemos que obtener 7 tiene la mayor probabilidad, pero eso no significa que el resultado de tirar dos dados sea más o menos aleatorio que el resultado de rodar uno.


Cuando tenga dudas sobre lo que sucederá con las combinaciones de sus números aleatorios, puede usar las lecciones que aprendió en la teoría estadística.

En la situación de OP, quiere saber cuál es el resultado de X * X = X ^ 2, donde X es una variable aleatoria distribuida a lo largo de Uniform [0,1]. Usaremos la técnica CDF ya que es solo un mapeo uno a uno.

Dado que X ~ Uniform [0,1] es cdf es: f X (x) = 1 Queremos la transformación Y <- X ^ 2, por lo tanto y = x ^ 2 Encuentre el inverso x (y): sqrt (y) = x esto nos da x en función de y. A continuación, encuentre el derivado dx / dy: d / dy (sqrt (y)) = 1 / (2 sqrt (y))

La distribución de Y se da como: f Y (y) = f X (x (y)) | dx / dy | = 1 / (2 sqrt (y))

Aún no hemos terminado, tenemos que obtener el dominio de Y. ya que 0 <= x <1, 0 <= x ^ 2 <1 para que Y esté en el rango [0, 1). Si desea verificar si el pdf de Y es de hecho un pdf, intégrelo sobre el dominio: Integrar 1 / (2 sqrt (y)) de 0 a 1 y, de hecho, aparece como 1. También, observe la forma del Dicha función se parece a lo que se publicó belisarious.

En cuanto a cosas como X 1 + X 2 + ... + X n , (donde X i ~ Uniform [0,1]) podemos apelar al Teorema del límite central que funciona para cualquier distribución cuyos momentos existan. Es por eso que la prueba Z existe en realidad.

Otras técnicas para determinar el pdf resultante incluyen la transformación jacobiana (que es la versión generalizada de la técnica cdf) y la técnica MGF.

EDITAR: Como aclaración, tenga en cuenta que estoy hablando de la distribución de la transformación resultante y no de su aleatoriedad . Eso es en realidad para una discusión separada. También lo que realmente obtuve fue para (rand ()) ^ 2. Para rand () * rand () es mucho más complicado, lo que, en cualquier caso, no dará como resultado una distribución uniforme de ningún tipo.


De acuerdo, intentaré agregar algún valor para complementar otras respuestas diciendo que está creando y utilizando un generador de números aleatorios.

Los generadores de números aleatorios son dispositivos (en un sentido muy general) que tienen múltiples características que pueden modificarse para ajustarse a un propósito. Algunos de ellos (de mí) son:

  • Entropía: como en Shannon Entropía
  • Distribución: distribución estadística (poisson, normal, etc.)
  • Tipo: cuál es la fuente de los números (algoritmo, evento natural, combinación de, etc.) y el algoritmo aplicado.
  • Eficiencia: rapidez o complejidad de ejecución.
  • Patrones: periodicidad, secuencias, carreras, etc.
  • y probablemente más ...

En la mayoría de las respuestas aquí, la distribución es el principal punto de interés, pero al combinar funciones y parámetros, creará nuevas formas de generar números aleatorios que tendrán características diferentes para algunas de las cuales la evaluación puede no ser evidente a primera vista.


La mayoría de estas distribuciones ocurren porque tienes que limitar o normalizar el número aleatorio.

Lo normalizamos para que sea todo positivo, que se ajuste dentro de un rango e incluso que se ajuste a las restricciones del tamaño de la memoria para el tipo de variable asignado.

En otras palabras, como tenemos que limitar la llamada aleatoria entre 0 y X (siendo X el límite de tamaño de nuestra variable) tendremos un grupo de números "aleatorios" entre 0 y X.

Ahora, cuando agrega el número aleatorio a otro número aleatorio, la suma estará en algún lugar entre 0 y 2X ... esto desvía los valores lejos de los puntos de borde (la probabilidad de sumar dos números pequeños y dos números grandes es muy pequeña cuando tienes dos números aleatorios en un gran rango).

Piense en el caso en el que tenía un número cercano a cero y si lo agrega con otro número aleatorio, seguramente aumentará de tamaño y se alejará de 0 (esto ocurrirá con los números grandes y es poco probable que tenga dos números grandes (números cercanos a X) devueltos por la función aleatoria dos veces.

Ahora, si tuviera que configurar el método aleatorio con números negativos y números positivos (que se extiendan por igual en el eje cero), este ya no sería el caso.

Por ejemplo, RandomReal({-x, x}, 50000, .01)entonces obtendría una distribución uniforme de los números en el lado negativo y positivo y si tuviera que sumar los números aleatorios, mantendrían su "aleatoriedad".

Ahora no estoy seguro de qué pasaría con el Random() * Random()lapso de negativo a positivo ... ese sería un gráfico interesante para ver ... pero debo volver a escribir el código ahora. :-PAG


La multiplicación de números terminaría en un rango de solución más pequeño, dependiendo de la arquitectura de su computadora.

Si la pantalla de su computadora muestra 16 dígitos rand(), digamos 0.1234567890123 multiplicado por un segundo rand(), 0.1234567890123, daría 0.0152415 algo que definitivamente encontraría menos soluciones si repitiera el experimento 10 ^ 14 veces.


La respuesta sería que depende, con suerte el rand () * rand () sería más aleatorio que rand (), pero como:

  • Ambas respuestas dependen del tamaño de bit de su valor
  • que en la mayoría de los casos se genera en función de un algoritmo pseudoaleatorio (que es principalmente un generador de números que depende del reloj de su computadora, y no mucho al azar).
  • haga que su código sea más legible (y no invoque algún dios vudú al azar con este tipo de mantra).

Bueno, si marca alguno de estos puntos arriba, le sugiero que vaya por el simple "rand ()". Porque su código sería más legible (no se preguntaría por qué escribió esto, porque ... bueno ... más de 2 segundos), fácil de mantener (si desea reemplazar su función rand con un super_rand).

Si desea un mejor aleatorio, le recomendaría que lo transmita desde cualquier fuente que proporcione suficiente ruido ( estática de radio ), y luego un simple rand()debería ser suficiente.


Utilice un registro de desplazamiento de realimentación lineal (LFSR) que implemente un polinomio primitivo.

El resultado será una secuencia de 2 ^ n números pseudoaleatorios, es decir, ninguno se repetirá en la secuencia donde n es el número de bits en el LFSR ... dando como resultado una distribución uniforme.

http://en.wikipedia.org/wiki/Linear_feedback_shift_register http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf

Use una semilla "aleatoria" basada en microsegundos del reloj de su computadora o tal vez un subconjunto del resultado de md5 en algunos datos que cambian continuamente en su sistema de archivos.

Por ejemplo, un LFSR de 32 bits generará 2 ^ 32 números únicos en secuencia (no 2 iguales) comenzando con una semilla dada. La secuencia siempre estará en el mismo orden, pero el punto de partida será diferente (obviamente) para una semilla diferente. Por lo tanto, si una secuencia posiblemente repetitiva entre las siembras no es un problema, esta podría ser una buena opción.

He usado LFSR de 128 bits para generar pruebas aleatorias en simuladores de hardware utilizando una semilla que es el resultado de md5 en datos del sistema que cambian continuamente.


Como otros ya han señalado, esta pregunta es difícil de responder ya que cada uno de nosotros tiene su propia imagen de aleatoriedad en su cabeza.

Por eso, te recomiendo que te tomes un tiempo y leas este sitio para tener una mejor idea de la aleatoriedad:

Para volver a la verdadera pregunta. No hay más o menos aleatorio en este término:

¡Ambos solo aparecen al azar !

En ambos casos, solo rand () o rand () * rand (), la situación es la misma: después de unos miles de millones de números, la secuencia se repetirá (!) . Que aparece al azar para el observador, ya que no sabe toda la secuencia, pero el equipo tiene ninguna verdadera fuente aleatoria - por lo que no puede producir aleatoriedad tampoco.

Ej .: ¿El clima es aleatorio? No tenemos suficientes sensores o conocimientos para determinar si el clima es aleatorio o no.


Considere que tiene un simple problema con el lanzamiento de una moneda donde incluso se considera cara y extraño se considera cola. La implementación lógica es:

rand() mod 2

Sobre una distribución suficientemente grande, el número de números pares debe ser igual al número de números impares.

Ahora consideremos un ligero pellizco:

rand() * rand() mod 2

Si uno de los resultados es uniforme, entonces todo el resultado debería ser uniforme. Considere los 4 resultados posibles (par * par = par, par * par impar = par, impar * par = par, par * impar = par). Ahora, en una distribución lo suficientemente grande, la respuesta debería ser incluso el 75% del tiempo.

Apostaría cara si fuera tú.

Este comentario es más una explicación de por qué no debería implementar una función aleatoria personalizada basada en su método que una discusión sobre las propiedades matemáticas de la aleatoriedad.


En realidad, cuando lo piensas rand() * rand()es menos aleatorio que rand(). Este es el por qué.

Esencialmente, hay el mismo número de números impares que los números pares. Y diciendo que 0.04325 es impar, y como 0.388 es par, y 0.4 es par, y 0.15 es par

Eso significa que rand()tiene la misma posibilidad de ser un decimal par o impar .

Por otro lado, rand() * rand()tiene sus probabilidades apiladas de manera un poco diferente. Digamos:

double a = rand(); double b = rand(); double c = a * b;

ay bambos tienen un 50% de probabilidad de ser par o impar. Sabiendo que

  • par * par = par
  • par * impar = par
  • impar * impar = impar
  • impar * par = par

significa que hay un 75% de probabilidad de que csea ​​parejo, mientras que solo un 25% de probabilidad es impar, haciendo que el valor sea rand() * rand()más predecible que rand(), por lo tanto, menos aleatorio.


Es fácil demostrar que la suma de los dos números aleatorios no es necesariamente aleatoria. Imagina que tienes un dado y un rollo de 6 caras. Cada número tiene una probabilidad de 1/6 de aparecer. Ahora digamos que tenías 2 dados y sumaste el resultado. La distribución de esas sumas no es 1/12. ¿Por qué?Porque ciertos números aparecen más que otros. Hay múltiples partitions de ellos. Por ejemplo, el número 2 es la suma de 1 + 1 solo, pero 7 puede estar formado por 3 + 4 o 4 + 3 o 5 + 2, etc. así que tiene una mayor probabilidad de que aparezca.

Por lo tanto, aplicar una transformación, en este caso, la adición a una función aleatoria no la hace más aleatoria, ni necesariamente conserva la aleatoriedad. En el caso de los dados anteriores, la distribución está sesgada a 7 y, por lo tanto, menos aleatoria.


Los randoms flotantes se basan, en general, en un algoritmo que produce un número entero entre cero y cierto rango. Como tal, al usar rand () * rand (), esencialmente estás diciendo int_rand () * int_rand () / rand_max ^ 2, lo que significa que estás excluyendo cualquier número primo / rand_max ^ 2.

Eso cambia la distribución aleatoria significativamente.

rand () se distribuye uniformemente en la mayoría de los sistemas, y es difícil de predecir si está correctamente sembrado. Use eso a menos que tenga una razón particular para hacer cálculos matemáticos (es decir, dar forma a la distribución de una curva necesaria).


No es exactamente obvio, pero rand()suele ser más aleatorio que rand()*rand(). Lo importante es que esto no es realmente muy importante para la mayoría de los usos.

Pero en primer lugar, producen diferentes distribuciones. Esto no es un problema si eso es lo que quieres, pero sí importa. Si necesita una distribución en particular, entonces ignore toda la pregunta "que es más aleatoria". Entonces, ¿por qué es rand()más aleatorio?

El núcleo de por qué rand()es más aleatorio (bajo el supuesto de que está produciendo números aleatorios de punto flotante con el rango [0..1], que es muy común) es que al multiplicar dos números de PF junto con mucha información en la mantisa, se obtiene alguna pérdida de información al final; simplemente no hay suficiente bit en un flotador de doble precisión IEEE para contener toda la información que estaba en dos flotadores de doble precisión IEEE seleccionados al azar de [0..1], y esos bits de información extra se pierden. Por supuesto, no importa mucho ya que (probablemente) no ibas a usar esa información, pero la pérdida es real. Tampoco importa realmente qué distribución produce (es decir, qué operación usa para hacer la combinación). Cada uno de esos números aleatorios tiene (en el mejor de los casos) 52 bits de información aleatoria: eso ''s cuánto puede contener un doble de IEEE, y si combina dos o más en uno, todavía está limitado a tener como máximo 52 bits de información aleatoria.

La mayoría de los usos de los números aleatorios no utilizan ni siquiera la cantidad de aleatoriedad que está disponible en la fuente aleatoria. Consigue un buen PRNG y no te preocupes demasiado por ello. (El nivel de "bondad" depende de lo que esté haciendo con él; debe tener cuidado al realizar la simulación o criptografía de Monte Carlo, pero de lo contrario probablemente pueda usar el PRNG estándar, ya que generalmente es mucho más rápido)


Podemos comparar dos matrices de números con respecto a la aleatoriedad utilizando la complejidad de Kolmogorov. Si la secuencia de números no se puede comprimir, entonces es lo más aleatorio que podemos alcanzar con esta longitud ... opción...


Suponiendo que rand()devuelve un número entre [0, 1), es evidente que rand() * rand()será empujado hacia 0. Esto es debido a la multiplicación xpor un número entre [0, 1)dará lugar a un número menor que x. Aquí está la distribución de 10000 números más aleatorios:

google.charts.load("current", { packages: ["corechart"] }); google.charts.setOnLoadCallback(drawChart); function drawChart() { var i; var randomNumbers = []; for (i = 0; i < 10000; i++) { randomNumbers.push(Math.random() * Math.random()); } var chart = new google.visualization.Histogram(document.getElementById("chart-1")); var data = new google.visualization.DataTable(); data.addColumn("number", "Value"); randomNumbers.forEach(function(randomNumber) { data.addRow([randomNumber]); }); chart.draw(data, { title: randomNumbers.length + " rand() * rand() values between [0, 1)", legend: { position: "none" } }); }

<script src="https://www.gstatic.com/charts/loader.js"></script> <div id="chart-1" style="height: 500px">Generating chart...</div>

Si rand()devuelve un entero entre [x, y]entonces tiene la siguiente distribución. Note el número de valores pares vs impares:

google.charts.load("current", { packages: ["corechart"] }); google.charts.setOnLoadCallback(drawChart); document.querySelector("#draw-chart").addEventListener("click", drawChart); function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function drawChart() { var min = Number(document.querySelector("#rand-min").value); var max = Number(document.querySelector("#rand-max").value); if (min >= max) { return; } var i; var randomNumbers = []; for (i = 0; i < 10000; i++) { randomNumbers.push(randomInt(min, max) * randomInt(min, max)); } var chart = new google.visualization.Histogram(document.getElementById("chart-1")); var data = new google.visualization.DataTable(); data.addColumn("number", "Value"); randomNumbers.forEach(function(randomNumber) { data.addRow([randomNumber]); }); chart.draw(data, { title: randomNumbers.length + " rand() * rand() values between [" + min + ", " + max + "]", legend: { position: "none" }, histogram: { bucketSize: 1 } }); }

<script src="https://www.gstatic.com/charts/loader.js"></script> <input type="number" id="rand-min" value="0" min="0" max="10"> <input type="number" id="rand-max" value="9" min="0" max="10"> <input type="button" id="draw-chart" value="Apply"> <div id="chart-1" style="height: 500px">Generating chart...</div>