• Sábado 21 de Diciembre de 2024, 11:03

Autor Tema:  Formula de N° aleatorios  (Leído 2425 veces)

Atsnael

  • Nuevo Miembro
  • *
  • Mensajes: 1
    • Ver Perfil
Formula de N° aleatorios
« en: Jueves 13 de Diciembre de 2012, 13:23 »
0
holaass, es la primera vez que entro a un foro para aclarar un par de dudas y he decidido meterme en este foro puesto que se que en el futuro podre aclarar mas dudas mias y tambien ayudar a los demas.
bien vayamos a lo que me esta coststando un poco hacer, estoy estudiando mi primer año de analista de sistemas y para un examen necesitamos crear un algoritmo que genere numeros aleatorios del 0 al 10. el tema es crear nuestro propio random sin necesidad de utilizar los recursos del visual para generar numeros aleatorios, nos hemos juntado con unos amigos y hemos generado la sigueinte formula   (A^X)*B/C donde A, B y C son numeros constantes y X actua como semilla y adopta el valor del ultimo numero que salio, para determinar el numero random utilizabamos el primer numero es decir si el resultado daba 7580 tomabamos el 7.
sin embargo se nos esta complicando un poco hacerlo con esta formula y ademas que  apra obtener el numero 10 debemos realizar varios controles que dependiendo de cirtos valores nos dee 10.
en fin lo que les queria pedir y yo y mi grupo le estariamos realmente agradecidos si alguien supiera enseñarnos una formula para poder obtener numeros aleatorios, (prefernetemente del 0 al 10) y si pudiera explicarnos como utilizar dicha formula.
desde ya muchisimas gracias gente, espero una pronta respuesta  :smartass:
por sierto para que sepan un poco de para que es el random que necesitamos, la idea es generar una lista con alumnos y que al precionar un boton se genere un numero aleatorio que nos dee el indice de la hubicacion de un alumno para poder obtener el nombre aleatoriamente en pantalla. muchisimas gracias por su tiempo :)

Nebire

  • Miembro HIPER activo
  • ****
  • Mensajes: 670
    • Ver Perfil
Re:Formula de N° aleatorios
« Respuesta #1 en: Viernes 21 de Diciembre de 2012, 08:56 »
0
No te voy a dar un trabajo que debes hacer tú,, pero si te voy a orientar, para que seas capaz de lograr algo decente, será más trabajo del que probablemente habíais previsto, pero el resultado merecerá el esfuerzo.

De entrada vuestro planteamiento falla porque es demasiado simple, le pedís mucho a una simple ecuación.

Los números nunca serán aleatorios, sino pseudoaleatroios, pero pueden serlo tanto que no resulten predecibles.

El algoritmo debe estar separado en 2 partes, IniciarTablas y GenerarNumero

IniciarTablas: podría constar en un preparativo de tablas que se calculan (y varían) cada vez que se reinicia el sistema. Y podría constar de los siguientes pasos

IniciarTablas:
Código: [Seleccionar]
1 - De entrada una buena semilla (sobretodo para iniciar el sistema generador) es tomar el
timer del sistema (una función que nos devuleve los milisegundos que han transcurrido desde
medianoche). Es bueno, porque no puedes programar al milisegundo cuando vas a llamar a una
función y que efectvamente suceda así.
      Semilla= timer //la llamada exacta depende del lenguaje pero todos tiene una función similar

2 - Vuestra ecuación ofrece números pero son muy dependientes entre sí. Es preferible partir de
números primos, por tanto, partiendo de una tabla de 1000 primos previamente ya conocida, fijate
que puedes usar como, semilla el timer para elegir un número primo dentro de dicha tabla de
primos. Por ejemplo si el timer marcara 34.567.637 (el día tiene 86.400sg. * 1000 msg.) , y tu
tabla consta de 1000 primos, podría usar el:
     primo = Tablaprimos( semilla modulo 1000 ) //es decir el primo guardado en la posición 637 de
la tabla.


3 - Ahora generar una buena dosis de números. El uso de los primos sería con cosas como, tomar
 los 100 decimales de la raíz cuadrada del número primo elegido de la tabla. Tampoco tiene por
qué ser los 100 primeros decimales, pueden ser del 325 al 425... un poco de imaginación. Incluso
 una vez obtenidos se pueden invertir su orden en la tabla de decimales 'T0', basandonos en si el
msg, del timer es par o impar.
Yo te digo raíz cuadrada, pero nada te impide que sea raíz cúbica, o 5ª... o que dicho valor se
tome de la semilla del timer. La raíz cuadrada siempre será más rápido...

El sistema no te da 100 decimales, los tipos de datos lo limitan. Tienes que preparar un algoritmo
para obtenerlo de forma similar a como lo hacemos manualmente cifra a cifra. Eso queda a vuestro
esfuerzo.


4 - Como verás las series de decimales que van ofreciendo los primos, es muy probable que no
den una buena entropia, habrá series donde unos números aparecerán con bastante más
frecuencia que otros. Esto se arregla si en vez de tomar 1 sola serie tomamos varias y sumamos
índice a índice cada valor de los 100 en la tabla y tomamos la unidad; un ejemplo:

 Sean 5 tablas con 100 valores ( los 100 decimales calculados de 5 primos distintos), generamos un bucle:
    Para 'n' desde 0 hasta 99  / recorremos todos los índices de la tabla
         t0(n) = (t1(n) + t2(n) + t3(n) + t4(n) + t5(n) ) modulo 10
    continuar bucle


5 - Ahora ya cuentas con una tabla cuya entropía desconoces, pero que probablemente sea
buena... conviene usar una serie más para obtener una tabla adicional puede ser otra partiendo
de los números primos o incluso una tabla tomando los decimales de pi, supongamos que es esta,
nuestra tabla ahora la calcularemos así:
    Para 'n' desde 0 hasta 99  // recorremos todos los índices de la tabla
         t0(n) =  t0(n) XOR pi(n)
    continuar bucle

IniciarTablas, ya está listo ahora podremos ceñirnos a GenerarNumero, que constaría de los
siguientes pasos:

GenerarNumero:
Código: [Seleccionar]
1 - Conviene tener 2 semillas, para la 1ª utilizaremos siempre el timer, la 2ª será uno de los
valores calculados en la fase, de entrada, es decir siendo la 1ª llamada valdra 0.

A la semilla del timer llamémosla 'SemT' y la otra 'Sem2'. Tendremos también un 'desplazador'
llamémosle 'Desp', luego verás para qué lo usamos....
      SemT = (timer modulo 100) //esto es nos quedamos sólo con 2 cifras, porque la  tabla 't0'
tiene sólo 100 elementos.
      //*Sem2 = 0 // al iniciarse el sistema, vale 0, en lo sucesivo retiene el valor internamente
      //*Desp  = 0 // al inicarse el sistema, vale 0, en lo sucesivo retiene el valor internamente

2 - El número a generar  (x) seguirá este camino:
  A - Calcular Sem2:
       Sem2 = (semT XOR Sem2)
  B - Hallar el número a devolver:
       x = t0((Sem2 + Desp) modulo 100)
  C - Actualizar el desplazador:
       Desp = ((Desp + 1) modulo 100)

Cada vez que se genera un número, actualizamos este valor, es como si la matriz entera se
rotase una posición. Pero como rotarla es costoso en tiempo, el desplazador consigue el mismo
efecto, con un coste de tiempo despreciable.

El desplazador consigue que tras cada petición, los números en la tabla ocupen una posición más
atrás. Esto hace que una semilla del timer igual que en otra ocasión y otra semilla secundaria igual
 que en otra ocasión, no genere el mismo número que la vez previa a causa del desplazador (salvo
 que en esa posición exista el mismo número que en la anterior).

Finalmente hay una tercera funcionalidad, que sería probar la entropía que ofrece nuestro
generador de números aleatorios. Esto no forma parte del algoritmo, pero si para estudiar su comportamiento.

ProbarEntropia:
Código: [Seleccionar]
1 - Para ello sería adecuado poner un bucle que genere pongamos 100.000 números y los
guarde en una matriz.

2 - Contar apariciones de cada número: Recorremos dicha tabla y contamos las veces que
aparece cada número, será buen generador siempre que la aparición de cada número se aproxime
a los 10.0000

3 - Contar repeticiones seguidas: como mínimo le pediríamos otra prueba a nuestro generador,
que nos diga cuantas veces seguidas aparece cada número.

Dado que si pidiéramos 10 números la probabilidad sería 1/10, para 100 números la probabilidad de
que saliera por ejemplo 6 y luego otra vez 6 sería 1/100, luego para 100.000 sería 5 veces
seguidas... es decir iniciaremos otro bucle que recorra los 100.000 números y contaremos cuantas
veces para cada número aparece seguido 5 o más veces.

Lo daremos por excelente si para cada número ocurre un máximo de 3 veces, (ojo 6 veces
seguidas un número(333333) no se ha de tomar como que 2 veces aparecen 5 veces seguidas un
número (33333x y x33333) o en total la media entre todos no supera 1'5 veces.


Bueno, como ves, tienes por donde guiarte para hacer algo decente... aunque más complejo que la simple ecuación de la que partíais.

La semilla se toma del timer, pero luego se combina (mediante XOR) con el resultado obtenido la vez anterior, a su vez se va rotando la tabla (virtualmente), en pasos de 1. y cada vez que el sistema se reinicia (por ejemplo cada vez que se enciende el ordenador) se eligen nuevas tablas, que son válidas hasta que de nuevo se apague el equipo.

p.d.: Olvidaba decirte, que los números generados serán en el rango 0-9, que imagino es lo que necesitais, no en el rango 0-10, como decías, creo que por error.
« última modificación: Viernes 21 de Diciembre de 2012, 09:33 por Nebire »
«Ma non troppo»
----> ModoVacaciones = False<----