Confusión sobre valores aleatorios (lanzamiento de color por computadora)
Ahora en las computadoras, el algoritmo utilizado para generar números aleatorios es el método de "congruencia lineal". La llamada congruencia lineal son en realidad las dos fórmulas siguientes. Suponiendo que I es una secuencia de números aleatorios, la relación entre Ij+1 e Ij es la siguiente:
Ij+1 =Ij * a+c (mod m)
o Ij +1 =Ij *a (mod m),
Entre ellos, a=16807, m=2147483647 se pueden tomar como constantes. Escriba un programa simple:
Long r;
voids can(long v)//Inicializa el número de semilla aleatoria.
{
r = v;
}
Long rand()//Generar números aleatorios.
{
r =(r * a+c)% m; //a, c, m son constantes.
return r;
}
Echemos un vistazo a la implementación de Borland, un poco más complicada, de (Random())
long long RandSeed = # # # #
Aleatorio largo sin firmar (valor máximo largo)
{
Longitud larga x;
Doble I ;
Final largo sin firmar
x = 0xffffffff
x+= 1;
RandSeed *=((龙龙) 134775813);
RandSeed+= 1;
rand semilla = rand semilla % x;
I =((doble)RandSeed)/(doble)0x ffffffff ; p>
final =(long)(max * I);
return (entero largo sin signo)final
}
2. Generado por computadora Los números aleatorios no son números verdaderamente aleatorios.
[Cita] Establecimos random(), que en realidad llama al generador de números pseudoaleatorios. Pero ¿qué es un generador de números pseudoaleatorios? Supongamos que necesita generar números aleatorios entre 1 y 10, cada número tiene la misma probabilidad. Lo ideal sería generar un valor entre 0 y 1, independientemente de los valores anteriores, y tener la misma probabilidad para cada valor en este rango, y luego multiplicar ese valor por 10. Tenga en cuenta que hay infinitos valores entre 0 y 1 y las computadoras no pueden proporcionar tal precisión.
Para escribir código para implementar un algoritmo como el mencionado anteriormente, el generador de números pseudoaleatorios generalmente genera un número entero entre 0 y n, y el número entero devuelto se divide por n. entre 0 y 1. Las llamadas posteriores al generador toman el número entero generado en la primera ejecución, lo pasan a una función para generar un nuevo número entero entre 0 y n, y luego divide el nuevo número entero por n para regresar. Esto significa que el número devuelto por cualquier generador de números pseudoaleatorios está limitado al número de números enteros entre 0 y n.
En los generadores de números aleatorios más comunes, ¿n es 232? (aproximadamente 4 mil millones), que es el valor máximo de un número de 32 bits. En otras palabras, el generador que encontramos a menudo puede generar hasta 4 mil millones de valores posibles. Y esta cifra de 4 mil millones no es grande en absoluto, es tan grande como la punta de tus dedos.
El generador de números pseudoaleatorios pasa este número como "semilla" a la función como entero inicial. Esta semilla mantendrá la bola en marcha. Los resultados de un generador de números pseudoaleatorios son impredecibles. Cada valor devuelto por un generador de números pseudoaleatorios está completamente determinado por el valor anterior que devolvió (en última instancia, la semilla lo es todo). Si conoce el número entero utilizado para calcular cualquier valor, puede calcular el siguiente valor devuelto por este generador.
Un generador de números pseudoaleatorios es, por tanto, un programa determinista que genera una secuencia completamente predecible (llamada flujo). Un PRNG bien escrito puede crear una secuencia que tenga las mismas propiedades que muchos números aleatorios reales. Por ejemplo:
PRNG puede generar cualquier número dentro de un rango con la misma probabilidad.
PRNG puede generar flujos con cualquier distribución estadística.
El flujo de números producidos por PRNG no tiene un patrón discernible.
Lo que PRNG no puede hacer es impredecible. Si conoce la semilla y el algoritmo, podrá calcular esta secuencia fácilmente.
Los números aleatorios generados por las computadoras generalmente son solo una secuencia de números con un período largo y no son números verdaderamente aleatorios. Es decir, los números aleatorios son generalmente números pseudoaleatorios, y cada número aleatorio es una secuencia establecida que comienza a partir de una semilla aleatoria (el período es muy largo). En términos generales, para que los números aleatorios sean más realistas, la semilla aleatoria generalmente se genera con referencia al reloj del sistema.
Mire el siguiente ejemplo, los lectores deberían poder entenderlo.
main()
{
int I;
scand(time(NULL));/*El valor del reloj puede ser recuperado de la computadora Leer y configurar automáticamente como semilla de número aleatorio*/
for(I = 0;i<10;i++){
printf("%10d ",1+( rand()% 6));/*Aquí 1 es un valor móvil igual al entero consecutivo deseado*/
}/*El primer número en el rango de valores b es el factor de escala; */
return(0);/*igual al ancho de rango requerido de valores enteros consecutivos;*/
}
Matemáticamente hablando, para Para obtener una secuencia aleatoria con un período más largo, puedes usar el siguiente método: (Vi esto en un libro. Puedes consultarlo para obtener más detalles. No lo recuerdo claramente, jaja)
punto flotante rand (long* idum)
{
int j; long k; static long iy = 0; static long iv[NTAB];
Temperatura flotante;
if(* idum & lt;=0||!iy)
{
if(-(* idum)& lt;1 )* idum = 1;
else * idum =-(* idum);
for(j = NTAB+7;j & gt=0;j - ){ p>
k =(* idum)/IQ;
* idum = IA *(* idum-k * IQ)-k * IR;
if(* idum <0 )
* idum+= IM;
if(j <NTAB)
iv[j]= * idum;
} iy = iv[0];}
k =(* idum)/IQ;
* idum = IA *(* idum-k * IQ)- k * IR; /p>
if(* idum & lt; 0)* idum+= IM
j = iy/NDIV
iy = iv[j ];
iv[j]= * idum;
if((temp = float(AM * iy))>RNMX) devuelve el tipo de punto flotante (RNMX);
De lo contrario, devuelve la temperatura;
}
[Nota:] Se dice que de acuerdo con el principio de funcionamiento de Randomize, la función Timer se utiliza para obtener el número de segundos que tienen. pasó desde la medianoche, y luego de acuerdo con El tamaño del valor aleatorio que se obtendrá "atenúa" el valor para que el valor resultante pueda denominarse un valor verdaderamente aleatorio. En mi opinión, éste también es un método creado por el hombre, que es determinista y cíclico. Todavía no es un número aleatorio verdadero, simplemente cambia la lógica de generación de números pseudoaleatorios. Además, el rand_seed modificado no debería ser artificial. (Nota: actualmente, los procesadores PIII de Intel tienen un generador de números aleatorios incorporado relacionado con la temperatura de la CPU, que es un generador de semillas eficaz. Un mejor método es generar números aleatorios basados en "eventos aleatorios", como los valores de entrada del teclado y el mouse. , interrupciones, lecturas de disco, etc.
Sin embargo, muchos servidores no tienen teclados ni ratones, y muchos productos de "caja negra" no tienen discos duros, por lo que es difícil encontrar una buena fuente de números aleatorios. Por supuesto, las claves de comunicación son igualmente inseguras. Sin embargo, como el estado de la red, no puede garantizar la aleatoriedad de los números aleatorios. El ruido eléctrico y el audio pueden ser buenas fuentes de números aleatorios, pero me temo que la mayoría de las personas no están dispuestas a agregar dichos equipos a sus computadoras. Pueden ocurrir problemas como fallas en el equipo y manipulación (influencia) externa. Este es un problema que se debe considerar para los servidores de puerta de enlace que deben manejar una gran cantidad de conexiones. Si la potencia actual de la CPU de la máquina se puede detectar con precisión como una semilla de número aleatorio, o algún otro método que cambie instantáneamente sin interferencia de factores humanos, se pueden generar números aleatorios con signo y requeridos.
3. Varios métodos para obtener números aleatorios
1. Generar una serie de números aleatorios.
Generalmente podemos usar j = 1+(int)(n * rand()/(rand _ max+1.0)) para generar un número aleatorio entre 0 y n.
if int x = rand()% 100; no se recomienda generar números aleatorios entre 0 y 100. Una mejor manera es: j =(int)(100.0 * rand()/(rand _ max+1.0)). Por supuesto, también podemos usar random(100). Random(n) se utiliza en los siguientes ejemplos.
2. Pantalla de números aleatorios. Si desea tomar un número aleatorio del 0 al 99, no puede ser 6.
Solución:
x = aleatorio(100);
mientras (x==6) {
x = aleatorio( 100 );
}
Otro ejemplo es si quieres tomar un número aleatorio del 0 al 99, en lugar de un múltiplo de 5:
x = aleatorio (100);
mientras ((x % 5)==0) {
x = aleatorio(100);
} p>
3. Tome números aleatorios de un rango continuo.
Por ejemplo, tome un número aleatorio del 40 al 50. Solución: x=aleatorio(11)+40.
4. Toma un número aleatorio de un conjunto de números aleatorios. Por ejemplo, seleccione aleatoriamente entre diez números: 67, 87, 34, 78, 12, 5, 9, 108, 999, 378. Solución: puede almacenar docenas de números en una matriz y luego usar números aleatorios del 0 al 9 como números de secuencia para lograr la recuperación aleatoria de datos.
a = nueva matriz (67, 87, 34, 78, 12, 5, 9, 108, 999, 378
j = aleatorio (10); >
x = a[j];
4. Generar números aleatorios con una distribución determinada.
Hay un muy buen artículo sobre esto, lea:
La generación de números aleatorios distribuidos no uniformemente y su aplicación en la investigación de simulación por computadora
Autor : Hu Xing·Liu Ben·Fang Xiangming·Jigan
Autor: Hu Xingben (Facultad de Medicina de Trabajadores de Hubei, Jingzhou 434000), ahora Universidad de Ciencias y Ciencias de Huazhong; Estudiante de doctorado en tecnología en el Departamento de Bioingeniería; Universidad Médica Sun Yat-sen, Facultad de Medicina de los Trabajadores de Hubei, Jingzhou 434000
Palabras clave: programación por computadora con distribución no uniforme;
Resumen: números aleatorios distribuidos no uniformemente Los números juegan un papel importante en la investigación de simulación por computadora, pero los lenguajes informáticos de alto nivel generalmente solo proporcionan funciones para generar números aleatorios distribuidos uniformemente, lo que dificulta el trabajo de investigación. El método propuesto en este artículo resuelve bien este problema y tiene una gran aplicabilidad.
Número de clasificación de la biblioteca china: O 242.438+0
Número de artículo: 1004-4337(2000)01-0059-02▲
1 propuesta de pregunta
p>Los lenguajes de programación informática de alto nivel más utilizados proporcionan la función de generar números aleatorios independientes r, que se distribuyen de forma continua y uniforme en el intervalo [0, 1]. Si simplemente transforma el número aleatorio generado en X=a+(b-a)r, puede obtener el número aleatorio X distribuido uniformemente en el intervalo [a, b].
Si se combina con funciones de redondeo o redondeo, también se pueden obtener números aleatorios discretos y distribuidos uniformemente, lo que resulta conveniente para las simulaciones por computadora. Pero en muchos casos, las simulaciones por computadora requieren el uso de números aleatorios no uniformes distribuidos según ciertas reglas. Por ejemplo, en la investigación de simulación de modelos de activación de canales iónicos, a menudo se utilizan números aleatorios distribuidos de manera no uniforme, como distribución exponencial, distribución logarítmica, distribución normal, distribución de Poisson, etc. En este momento, puede escribir una función o procedimiento en el programa fuente para generarlo. En los últimos años de trabajo de investigación de simulación por computadora [1, 2], hemos utilizado una gran cantidad de números aleatorios distribuidos de manera no uniforme y hemos logrado el éxito. Dado que los números aleatorios discretos se pueden convertir a partir de números aleatorios continuos mediante redondeo o redondeo, este artículo solo se centra en los principios de generación y ejemplos de aplicación de números aleatorios continuos distribuidos no uniformemente, y brinda las funciones correspondientes y las funciones escritas en un lenguaje similar a PASCAL. proceso[3]. Cualquiera que haya dominado el conocimiento de cualquier tecnología de programación de lenguajes informáticos de alto nivel y estructura de datos puede convertirlos fácilmente en un programa que pueda ejecutarse en la computadora, con gran flexibilidad y practicidad.
2 Principio de producción
Supongamos que la variable aleatoria continua X es función de la variable aleatoria continua r.
x= (r) (1)
Según el conocimiento de probabilidad y estadística, los valores de la función de distribución de X y R en los puntos correspondientes deben ser iguales, es decir , se genera la transformación inversa de R.
F(x)=F(r)(2)
Donde r es la solución de la fórmula (1), es decir, r =-1 (x) = ψ ( incógnita).
En casos especiales, si R es una variable aleatoria continua distribuida uniformemente en el intervalo [0, 1], entonces R
F(x)=F(r)=r ( 3)
Su función inversa
x=F-1(r) (4)
Tiene una función de distribución f. Ahora demuestra que debido a la distribución La función aumenta monótonamente, por lo que existe su función inversa. Según el conocimiento de probabilidad, para cualquier número real x, existe
p(X & lt; x) = P(F-1(R) & lt; ))
Debido a que R es una variable aleatoria continua distribuida uniformemente en el intervalo [0, 1], P (r
La fórmula (4) muestra que es necesario generar una distribución que obedezca a una determinada distribución Para un número, primero puede encontrar la fórmula analítica de la función inversa de su función de distribución y luego sustituir el valor de un número aleatorio uniforme en el intervalo [0, 1] para el cálculo
3 ejemplos de aplicación<. /p> p>
La función de densidad generada en el Ejemplo 1 satisface la distribución exponencial de números aleatorios, donde α>0
Porque, la función de distribución es:
Es se puede obtener de la fórmula (4)
(5)
Cuando r es un número aleatorio uniforme en el intervalo [0, 1], 1-r también es el intervalo aleatorio uniforme números dentro de [0, 1], por lo que la ecuación (5) también se puede simplificar a:
(6)
Supongamos que el lenguaje informático de alto nivel ha proporcionado un método para generar uniforme La función RND(0) de números aleatorios distribuidos en el intervalo [0, 1] y la función de lenguaje similar a Pascal utilizada para generar números aleatorios que obedecen a una distribución exponencial se pueden escribir de la siguiente manera según la ecuación (6):
FUNC get _ exp _ random(alpha:real):real;
{Genera números aleatorios distribuidos exponencialmente, el parámetro de valor α es un parámetro proporcional}
get _ exp _ random =- ln(RND(0))/alpha;
ENDF; {Obtener aleatoriedad exponencial}
El ejemplo 2 genera números aleatorios que obedecen a una distribución normal.
Positivo. La distribución de estado x~n (a,σ) se puede obtener convirtiendo la distribución normal estándar x′~n(0,1) en x = a+σx′. números aleatorios que obedecen a la distribución normal estándar. La función de densidad de la distribución normal estándar es:
(7)
Pero su función de distribución no se puede expresar en una forma analítica limitada. lo que trae dificultades a la transformación, pero la siguiente transformación se puede utilizar para generar números aleatorios.
Supongamos que r1 y r2 son dos números aleatorios independientes distribuidos uniformemente en el intervalo [0, 1], hacemos la siguiente transformación, entonces,
(8)
Luego transfórmalo inversamente en:
(9)
C en la fórmula (9) es una constante. De esto se puede deducir que su función de densidad es:
(10)
Comparando la fórmula (10) y la fórmula (7), sabemos que X1 y X2 son dos Una variable aleatoria con una distribución de estado, por lo que la fórmula (8) es equivalente a la fórmula (4) para generar números aleatorios. A partir de esto, podemos escribir el proceso de generación de números aleatorios que obedezcan la distribución normal estándar en un lenguaje tipo PASCAL de la siguiente manera:
PROC Gaussiano (VAR x1, x2: real);
{Generar un par de números aleatorios distribuidos normalmente, pasando números aleatorios para los parámetros variables x1 y x2}
pi:= 3.14159265; {asignar valor π}
r 1:= RND(0 ); R2:= RND(0);
s:= SQRT(-2 * ln(r 1)); {Asignación de variables intermedias}
x 1:= s * cos(2 * pi * R2);
x2:= s * sin(2 * pi * R2);
{Se asignan números aleatorios con distribución normal a posibles parámetros de Variable }
ENDP; Gaussiano
Cada llamada de este procedimiento genera dos números aleatorios distribuidos normales estándar ortogonales.