Hola a todos, os adjunto el código fuente de un módulo que genera números aleatorios usando el método Mersenne twister MT19937 de Makoto Matsumoto.
le he añadido el alleged RC4
Si no es demasiado complicado, se podría integrar en Bennu y que a través de una opción se pudiera elegir entre utilizar un sistema u otro, no?
Ya se que podría buscar, pero prefiero preguntar.
¿Cuales son las (seguramente grandes) ventajas de este método de generación de aleatorios?
Quote from: PiXeL on October 05, 2010, 12:06:27 PM
Si no es demasiado complicado, se podría integrar en Bennu y que a través de una opción se pudiera elegir entre utilizar un sistema u otro, no?
Para eso están los includes, para elegir qué librería usar en cada proyecto.
Lo cierto es que una pequeña documentación de las funciones disponibles, su uso y sus características básicas irían muy bien, es que no hay ni leeme ;)
:D. para eso está el test.prg.
Todas las funciones tienen un prefijo indicando el algoritmo empleado.
Pero vamos es como cualquier rand de cualquier lenguaje de programacion :D.
* Las funciones que terminan en "_seed" son para establecer la semilla de origen del algoritmo rand, y puede haber de dos tipos una sin parámetros de entrada, que usa la hora de sistema para establecer la semilla y otra con un parámetro de entrada que usa ese parámetro de entrada para establecer la semilla.
* Las funciones que tienen la palabra "rand" son para obtener un número aleatorio usando el algoritmo. Puenden tener un parámetro de entrada que sirve para indicar hasta qué numero quieres que te de la secuencia y van desde 0 hasta ese número, y luego pueden no tener parámetro y estas irán desde 0 hasta 1 (son para números reales aleatorios)
¿Te refieres a ESTE prg?
[code language="bennu"]import "mod_say";
import "mod_rands";
Process Main()
local
float val;
Begin
MT19937_SEED();
Say (MT19937_RAND(100));
Say (MT19937_RAND(100));
Say (MT19937_RAND(100));
say ("Alleged RC4");
ALRC4_SEED();
Say (ALRC4_RAND(100));
Say (ALRC4_RAND(100));
Say (ALRC4_RAND(100));
Say (ALRC4_RANDF(100));
Say (ALRC4_RANDF(100));
Say (ALRC4_RANDF(100));
End[/code]
Sí, desde luego es muy explicativo :D
Eso mismo que has escrito debería ir en un TXT, o expresado de distinta forma pero con la misma información :)
¿Y algún algoritmo para obtener números aleatorios dentro de un intervalo siguiendo una distribución Normal o Poisson?
Para que me entendáis: La altura del ser humano no es una distribución uniforme, tendemos a 1.75m casi todos, y puntualmente algunos se alejan de la normal y miden 1.50m o 2.00m.
DCelso te doy el karma que ayer olvidé darte, estaba seguro de que nos ibas a venir con esto xDDD
Quote from: Windgate on October 05, 2010, 07:50:43 PM
¿Y algún algoritmo para obtener números aleatorios dentro de un intervalo siguiendo una distribución Normal o Poisson?
Para que me entendáis: La altura del ser humano no es una distribución uniforme, tendemos a 1.75m casi todos, y puntualmente algunos se alejan de la normal y miden 1.50m o 2.00m.
DCelso te doy el karma que ayer olvidé darte, estaba seguro de que nos ibas a venir con esto xDDD
Me imagino que esto no va aqui ya que poco tiene que ver con las extensiones, pero como Wind lo ha preguntado aqui, respondo por aqui.
Teniendo el random para la uniforme 0,1 tienes cualquier distribucion.
Para la Poisson se ve que es tan sencillo como esto:
// Returns a number (of points in a unit length) which
// has a Poission distribution with intensity c.
public int poisson(double c) {
int x = 0;
double t = 0.0;
for (;;) {
t = t - Math.log(Math.random())/c;
if (t > 1.0)
break;
x = x + 1;
}
return x;
}
Para la normal el metodo de Box–Muller parece lo mas sencillo de todo.
(http://upload.wikimedia.org/math/d/4/5/d45b69cbca8f444a9a3621b90bbebf31.png)
donde U y V son distribuciones uniformes (0,1)
La X y la Y son dos distribuciones normales independientes de media 0 y desviación 1. Despues solo tienes que transformalas a la media y desviación que quieras y ya lo tienes. (x*desviacion)+media y ya vas que andas!
Sí, me imaginaba una solución así, pero la idea es no tener que operar cada vez sino tenerla a modo de dll y pasar como parámetros la media y la desviación despreocupándote de tener o no conocimientos de estadística :D
No obstante te doy un karma por si algún día es útil que nunca se sabe :P
Yo no tengo ni idea de hacer dlls, pero vamos para la poisson el codigo ya esta hecho (java, pero totalmente implementable en cualquier otro lenguaje), y el de la Normal tiene de ser muy sencillote de hacer (diria más, por casualidades de la vida yo estudie estadistica y me parece que en alguna practica que tuve, implemente ese mismo metodo que he puesto, eso si, en pascal seguramente).
Asi que a ver si alguno de los dll-guru del foro se anima y te empaqueta una bonita dll ;D
Bueno, he encontrado una página en la que hay librerías C++ para generar numeros aleatorios uniformes y otra para numeros aleatorios no uniformes para las siguientes distribuciones: normal, truncated normal, bernoulli, poisson, binomial, hypergeometric, Wallenius' and Fisher's noncentral hypergeometric, multinomial, multivariate hypergeometric, and multivariate Fisher's and Wallenius' noncentral hypergeometric distributions
http://www.agner.org/random/
A ver si me armo de valor y rearmo este módulo con estas dos libs :D.
ostras, esto es lo que hace el rand de c
void srand(unsigned int seed)
{
holdrand = (long) seed;
}
int rand()
{
return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
con menos líneas y más rápido, imposible. :D
En fin el algoritmo sería algo como el nuevo valor es igual al antiguo valor multiplicado por un numeraco al que luego le sumo otro numeraco para luego dividirlo 16 veces entre dos y finalmente quedarme con los últimos 15 bits.
:D
No se comieron mucho el coco no...
Pues aunque os parezca mentira es el metodo mas comun para generar los rand:
http://en.wikipedia.org/wiki/Linear_congruential_generator
Bueno, pues la he programado en bennu y parece que va bien y todo :D.
import "mod_say"
import "mod_time"
global
seed;
end
function srand(value)
begin
seed = value;
end
function rand()
begin
seed = seed * 214013 + 2531011;
return ( (seed >> 16) & 07fffh);
end
function rand_between(vstart, vend)
begin
return (rand() % (vend-vstart+1) +vstart);
end
process main()
private
i;
valor;
float media;
numeros = 1000;
begin
srand(time());
for (i=0;i<numeros;i++)
valor = rand();
say(valor);
media= media +valor;
end
media = media /numeros;
say("media:"+media);
media = 0;
for (i=0;i<1000;i++)
valor = rand_between(10,20);
say(valor);
media= media +valor;
end
media = media /numeros;
say("media:"+media);
end
Yo he visto un generador de números aleatorios en hardware, que si está bien hecho es cíclico y se dan todos los números, a base de desplazamientos y puertas XOR, así que... ;D