Programación General > C/C++

 Función Random

(1/2) > >>

bria:
Hola....

podrían ayudarme a generar floats entre 2 variables ( + - randmax)?
Ahora estoy ejecutando lo siguiente:
for (i=0; i<n_inp+1; i++) {
for (h=0; h<n_hid; h++) {
w1[h] = rnd(-randmax,randmax);
}
}

y cual ha sido mi sorpresa cuando he visto que siempre se inicializa con los mismos valores (aunque respeta los limites de + - randmax). rnd no es una función propia de Builder, aunque la acepta (no sale en la ayuda). randmax es una varibale que decide el usuario y que suele estar entre 0,0001 y 0,5.

Mirando la ayuda, habla solo de generar valores entre 0 y 1, que no me sirve, y algo más que no he llegado a entender (si, lo siento.....)

Si alguien fuera tan amable de echarme una mano....


PD: ya he probado a añadir un randomize antes de llamar a la función y el resultado ha sido el mismo.

chuidiang:
Las funciones de generar numeros aleatorios suelen generarlos entre dos limites fijos. Para flotantes, suele ser entre 0.0 y 1.0 (excluido en 1.0)
Luego tu puedes convertirlo a tu rango echando una cuenta. Si lo quieres entre -randmax y +randmax, la cuenta es algo como esto


--- Código: Text --- aux = valor * (2 * randmax);   // Esto convierte el valor aleatorio entre 0.0 y 2*randmax aux2 = aux - randmax;  // Esto lo convierte al rango que tu quieres.  

Las funciones aleatorias no son aleatorias realmente. Hacen unas cuentas y obtienen un valor pseudo-aleatorio. En cada ejecución del programa, las cuentas son las mismas y obtienes los mismos numeros aleatorios.

Hay una funcion srand() en la que se da un numero inicial para empezar esas cuentas. Es necesario llamar a esta funcion pasandole un entero distinto en cada ejecucion del programa. Lo habitual es pasar el tiempo actual. Solo hay que llamar a esa función una única vez. En C para solaris el código es el siguiente


--- Código: Text --- main (){   srand48 (time(NULL));  // se pasa a srand la fecha-hora actual   ...    while (...)   {       double valor = drand48();  // Numeros aleatorios       ...   }}  
No se las funciones de fecha hora en borland, pero no te costará encontrarla.

En unix hay rand() que da un entero aleatorio y se inicializa con srand()
y hay drand48() que da un double aleatorio y se inicializa con srand48(). Mira si en borland hay varias srand() y asegurate de usar la que corresponda al rand() que estés usando.

Se buena.

QliX=D!:

--- Citar ---Las funciones aleatorias no son aleatorias realmente. Hacen unas cuentas y obtienen un valor pseudo-aleatorio. En cada ejecución del programa, las cuentas son las mismas y obtienes los mismos numeros aleatorios.
--- Fin de la cita ---

Esto en realidad no es verdad...
Dps de muchas ejecuciones los valores se empiezan a repetir.
Estos valores aleatorios no son adecuados para cosas sobre seguridad, pero si para aleatorizar metodos o datos en juegos, etc.
El C usa un Generador congruencial linear como algoritmo.

Ruben3d:

--- Cita de: "QliX=D!" ---
--- Citar ---Las funciones aleatorias no son aleatorias realmente. Hacen unas cuentas y obtienen un valor pseudo-aleatorio. En cada ejecución del programa, las cuentas son las mismas y obtienes los mismos numeros aleatorios.
--- Fin de la cita ---

Esto en realidad no es verdad...
--- Fin de la cita ---

Hola a todos.

Quería decir que chuidiang sí tiene razón (aunque es algo incompleto). Efectivamente, como bien dice QliX=D!, la función de generación de números aleatorios en C (y en muchos otros lenguajes) implementa un generador congruente lineal.

A grandes rasgos, un generador de estas características toma un número, llamado semilla, y le aplica una transformación (no la voy a explicitar aqui). Este nuevo número así generado pasa a ser la nueva semilla, sustituyendo al anterior. A continuación, este número es dividido entre cierto número (llamemoslo m) (de ninguna manera elegido al azar), con lo que se obtiene un nuevo número en el rango [0.0,1.0), que será el retorno de la función.

Es cierto que, como señaló QliX=D!, la serie de números generada comenzará a repetirse tras cierta cantidad de pasos. Si el valor de m está bien elegido (además de otros usados en la transformación) conseguiremos un generador de período completo (de tamaño m-1). Para garantizar esto, m ha de ser un primo. Ahora bien, para maximizar el tamaño del periodo, hemos de elegir un m grande, que en máquinas de 32 bits puede ser 2^31-1.

Así pues, siempre que se inicie el programa y se empiecen a generar números aleatorios se generará la misma secuencia (como dijo chuidiang) ya que la generación es llevada a cabo por la aplicación consecutiva de una serie de operaciones constantes (con constantes quiero decir que siempre son las mismas y no dependen de ningún factor externo). Sin embargo, si nos fijamos bien en el proceso que he descrito más arriba, la generación se basa en ir aplicando transformaciones a un valor llamado semilla. Dando un valor inicial diferente en cada ejecución (usando la hora, por ejemplo) a la semilla conseguiremos series de números diferentes cada vez que ejecutemos el programa.


--- Cita de: "QliX=D!" ---Estos valores aleatorios no son adecuados para cosas sobre seguridad, pero si para aleatorizar metodos o datos en juegos, etc.

--- Fin de la cita ---

Francamente, opino que los valores así generados sí son aptos para aplicaciones seguras. No hay más que fijarse en el tamaño del periodo: m-1 = (2^32-1)-1 = 2147483646. Lo que más puede poner en compromiso la fiabilidad de un sistema basado en un generador de este tipo es la correcta elección de ciertas constantes que se utilizan (una de ellas es m). Una elección al azar o no estudiada detenidamente puede dar lugar a generadores que altenernen entre números pares o impares, que tiendan a generar más veces ciertos números o que se reduzca su periodo drásticamente, propiedades difícilmente deseables.

Bueno, espero haber dejado claro con esta explicación cómo se generan los números aleatorios en los ordenadores. Espero que le sea de ayuda a alguien.

Un saludo.

Ruben3d

QliX=D!:

--- Cita de: "Ruben3d" ---
--- Cita de: "QliX=D!" ---Estos valores aleatorios no son adecuados para cosas sobre seguridad, pero si para aleatorizar metodos o datos en juegos, etc.

--- Fin de la cita ---

Francamente, opino que los valores así generados sí son aptos para aplicaciones seguras. No hay más que fijarse en el tamaño del periodo: m-1 = (2^32-1)-1 = 2147483646. Lo que más puede poner en compromiso la fiabilidad de un sistema basado en un generador de este tipo es la correcta elección de ciertas constantes que se utilizan (una de ellas es m). Una elección al azar o no estudiada detenidamente puede dar lugar a generadores que altenernen entre números pares o impares, que tiendan a generar más veces ciertos números o que se reduzca su periodo drásticamente, propiedades difícilmente deseables.
 
--- Fin de la cita ---
NO! NO! Y NO!.
realmente no es apto para aplicaciones seguras por que los generadores congruenciales son muy sencilllos de "adivinar"
El periodo de 2147483646 es demasiado pequeño para cualquier tipo de implementacion segura.
En cierta manera con un generador congruencial haciendo una analisis de varios valores se peude llegar a adivinar un "rango" de numeros donde puede caer nuestro proximo numero.

Si pasean por varios sitios de la red dice explicitamente que para requerimientos de seguridad no son suficientemente bueno los generadore congruenciales, por ejemplo: Quoteado de: http://webs.ono.com/usr005/jsuarez/aleat3.htm


--- Citar ---El generador lineal congruencial.

Ponemos como ejemplo este generador porque es uno de los más difundidos siendo a la vez uno de los más débiles y no apto para uso criptográfico. Se utiliza en la mayoría de las funciones rand() y similares.

La forma general de es: Xi+1=(a.Xi + b ) mod m donde X0 sería la semilla del generador. La salida suele ser el número Xi/m, un número en coma flotante en el intervalo [0,1).

Algunas propiedades de estos generadores:

   1. El módulo m es una cota superior del número de valores diferentes que puede tomar la semilla.
   2. Si Xi vuelve a tomar el valor de la semilla inicial la secuencia se repetirá cíclicamente.
   3. Todas las secuencias producidas por este tipo de generador si se prolongan lo suficiente (periodo) acaban en un ciclo que se repite indefinidamente.

Un buen generador lineal tendrá un periodo tan largo como sea posible (es decir m). Este máximo se alcanza si y sólo si se cumplen las tres siguientes condiciones [Knuth]

a) b es primo con m
B) a-1 es múltiplo de p para todo primo p que divida a m
c) a-1 es múltiplo de 4 siempre que m sea múltiplo de 4

Habitualmente se toma como m una potencia de 2 más de 1 de modo que se puede coger por ejemplo b=1 y a un número impar.

No sólo este tipo de generador sino todos los de tipo polinómico congruencial, es decir:

x= (anxn + ... + a1x + a0) mod m

son predecibles y por tanto inútiles para cualquier cifrado serio.

--- Fin de la cita ---

Tambien de:
http://www.dwheeler.com/secure-programs/Se...om-numbers.html

en una parte dice:

--- Citar ---Most non-cryptographic library PRNGs are some variation of ``linear congruential generators'', where the ``next'' random value is computed as "(aX+B) mod m" (where X is the previous value). Good linear congruential generators are fast and have useful statistical properties, making them appropriate for their intended uses. The problem with such PRNGs is that future values can be easily deduced by an attacker (though they may appear random)

--- Fin de la cita ---


Bueno y no muchos mas.... pero hay mas para poner.
En si, el problema es que es ADIVINABLE el proximo numero.


HAy formas de "engañar" al atacante y hacer que no se de cuenta de que uso un congruencial lineal... pero bueno, no way... usen otro tipo... no usen este estilo de PRNG y listo :D

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

Ir a la versión completa