Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« : Mayo 29, 2006, 13:05:23 » |
|
Necesito un generador de números aleatorios para C, no es necesario que sea demasiado bueno.
Estoy usando la función random() de stdlib.h . La cosa es que en cada ejecución se repite la misma secuencia. Necesito, simplemente, que se barajen los números de manera que en cada ejecución aparezca una secuencia diferente.
¿Alguien sabe?
|
|
|
|
|
En línea
|
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #1 : Mayo 29, 2006, 13:24:42 » |
|
Una forma para generar 1 y 0 aleatorios es usar la funcion time:
#include <time.h>
#include <stdlib.h>
main(){
time_t t;
srand((unsigned) time(&t)); /* esto solo es necesario 1 vez */
numaleatorio=rand() % 2;
}
|
|
|
|
|
En línea
|
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #2 : Mayo 29, 2006, 13:39:14 » |
|
Muchas gracias, campeón. 
|
|
|
|
|
En línea
|
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #3 : Mayo 29, 2006, 13:43:05 » |
|
de nada!!!
Ahora voy a ver si entiendo de una vez por todas las listas que son una pesadilla!!!!
:engard:
|
|
|
|
|
En línea
|
|
|
|
Nexus 7
Usuario
Fotones: 61
Desconectado
Mensajes: 4839
El señor de las máquinas.
|
 |
« Respuesta #4 : Mayo 29, 2006, 15:01:26 » |
|
Hola.
No sé si ocurrirá de forma similar en C, pero en Pascal había dos cuestiones a este respecto.
Por un lado estaba la función que generaba el aleatorio {random(x)}, y por otro lado estaba el "motor" de aleatorios {randomize}. El problema que expones es el problema típico que ocurriría en Pascal si solamente se utilizara el primero sin el segundo, o si se utilizara el segundo cada vez que utilizas el primero.
Para solucionar ese problema en Pascal (que no tiene porqué ser así en C) deberíamos utilizar el "randomize" una única y exclusiva vez antes de emplear el "random" por primera vez. Esto es, primero el "randomize" para que controle todo lo concerniente a los aleatorios, y luego el random cada vez que queramos obtener un aleatorio.
Saludos.
|
|
|
|
|
En línea
|
|
|
|
Tesseract
Usuario
Fotones: 38
Desconectado
Mensajes: 860
|
 |
« Respuesta #5 : Mayo 29, 2006, 15:55:46 » |
|
Precisamente en Pascal lo que hace el randomize es utilizar el reloj para inicializar el generador de números aleatorios. Viene a ser lo mismo que en el C, sí.
|
|
|
|
|
En línea
|
"Si he visto más lejos que otros, es porque estoy rodeado de enanos". Murray Gell-Mann
"Sí -repite la hormiga-, / he visto las estrellas, / subí al árbol más alto / que tiene la alameda / y vi miles de ojos / dentro de mis tinieblas".
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #6 : Mayo 29, 2006, 21:01:51 » |
|
Hola.
No sé si ocurrirá de forma similar en C, pero en Pascal había dos cuestiones a este respecto.
Por un lado estaba la función que generaba el aleatorio {random(x)}, y por otro lado estaba el "motor" de aleatorios {randomize}. El problema que expones es el problema típico que ocurriría en Pascal si solamente se utilizara el primero sin el segundo, o si se utilizara el segundo cada vez que utilizas el primero.
Para solucionar ese problema en Pascal (que no tiene porqué ser así en C) deberíamos utilizar el "randomize" una única y exclusiva vez antes de emplear el "random" por primera vez. Esto es, primero el "randomize" para que controle todo lo concerniente a los aleatorios, y luego el random cada vez que queramos obtener un aleatorio.
Saludos.
Sí, hace tiempo, en mis primeros pinitos en C con Windows, recuerdo usar la función randomize(), precisamente  . Pero en Linux parece que no existe.
En cualquier caso, la solución de Miguel-MurcIa digo...nesimo, funciona muy bien. Pronto veréis mi criatura...MWAHAHAHA  .
|
|
|
|
|
En línea
|
|
|
|
|
n0mad
|
 |
« Respuesta #7 : Mayo 29, 2006, 22:02:07 » |
|
Que estas haciendo??? Dios mio!!!

|
|
|
|
|
En línea
|
 "Get out of my way, or I'll pee right through ya!" Richard Feynman
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #8 : Mayo 29, 2006, 23:58:09 » |
|
ya nos lo dirá... wajajajajaja
|
|
|
|
|
En línea
|
|
|
|
|
Visitante
|
 |
« Respuesta #9 : Junio 01, 2006, 22:42:00 » |
|
No debe de haber ningun programa que te genere un numero perfectamente aleatorio. Siempre contendran algun punto de acumulacion. De todos modos, que de la inmensidad de los numeros el programa te muestre un numerillo de unos cuantos digitos resulta sospechoso.
|
|
|
|
|
En línea
|
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #10 : Junio 01, 2006, 23:39:25 » |
|
Hay test que te permiten parametrizar lo bueno o malo que es un algoritmo de aleatoriedad. Por ejemplo hay uno que es sencillito que es asignar esos numeros a una nube x, y, z y ver que pasa.
Un saludo!
|
|
|
|
|
En línea
|
|
|
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #12 : Junio 02, 2006, 00:03:03 » |
|
Como se nota que nos han enseñado en el mismo sitio... jejeje
|
|
|
|
|
En línea
|
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #13 : Junio 02, 2006, 00:08:27 » |
|
Como se nota que nos han enseñado en el mismo sitio... jejeje
No. Autónoma :bostezo: . 
|
|
|
|
|
En línea
|
|
|
|
nesimo
Usuario
Fotones: 2
Desconectado
Mensajes: 620
|
 |
« Respuesta #14 : Junio 02, 2006, 00:11:19 » |
|
jejeje... vaya.. a mi rafa me enseño una imagen parecida a la que tu me has enseñado.
¿Por cierto... que tal es la funcion random de C?
|
|
|
|
|
En línea
|
|
|
|
JoanD
Usuario
Fotones: 1
Desconectado
Mensajes: 91
|
 |
« Respuesta #15 : Junio 05, 2006, 14:54:23 » |
|
He hecho una pequeña simulación en C#.
Quiero obtener numeros aleatorios en el rango de numeros enteros entre 0 y 10 (ambos incluidos).
Igual que en C uso la función Random la cual usa el reloj del sistema para inicial una semilla de numeros aleatorios:
Random aleatorio = new Random (unchecked((int) DateTime.Now.Ticks));
Luego la funcion aleatorio.NextDouble() obtiene valores comprendidos entre 0 y 1.
Para convertir esos valores en el rango de 0 a 10 lo que hago es multiplicar por 10 y recoger el resultado en un array de numeros enteros (valores[])
El programa va generando valores hasta que se pulsa el botón "Cancelar"
El código empleado en el botón "Acceptar" del formulario es el siguiente:
private void btAcceptar_Click(object sender, System.EventArgs e)
{
Random aleatorio = new Random (unchecked((int) DateTime.Now.Ticks));
n=10 ;
valores = new UInt64[n+1];
cancel=false;
while (!cancel)
{
valores[Convert.ToInt16((aleatorio.NextDouble()*n))]++;
Application.DoEvents();
}
}
Lo mas sorprendente es que los valores extremos 0 y 10 obtienen una frecuencia de aparición del órden de la mitad de los otros valores.
Por ejemplo en una simulación he obtenido los siguientes valores:
0 125397
1 250213
2 250430
3 250286
4 249896
5 251711
6 250801
7 250460
8 250578
9 250828
10 124691
Seguramente la explicación sea que el valor 0 sólo se obtiene cuando el valor aleatorio * 10 es menor de 0.5 mientras que para el valor 1, por ejemplo, el rango debe ser entre 0.5 y 1.5 (o sea el doble). Para el valor 10 sucede algo parecido: sólo se obtiene el valor 10 cuando el numero aleatorio * 10 da un valor igual o superior a 9.5
¿Cómo hariais para conseguir que todos los numeros tengan la misma frecuéncia de aparición?
|
|
|
|
|
En línea
|
Saludos
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #16 : Junio 05, 2006, 16:21:29 » |
|
Seguramente la explicación sea que el valor 0 sólo se obtiene cuando el valor aleatorio * 10 es menor de 0.5 mientras que para el valor 1, por ejemplo, el rango debe ser entre 0.5 y 1.5 (o sea el doble). Para el valor 10 sucede algo parecido: sólo se obtiene el valor 10 cuando el numero aleatorio * 10 da un valor igual o superior a 9.5
¿Cómo hariais para conseguir que todos los numeros tengan la misma frecuéncia de aparición?
Esto no lo entiendo. Si no he entendido mal, te quedas con la parte entera, ¿no?. Esa explicación del 0.5 al 1.5 no la veo  .
|
|
|
|
|
En línea
|
|
|
|
JoanD
Usuario
Fotones: 1
Desconectado
Mensajes: 91
|
 |
« Respuesta #17 : Junio 05, 2006, 16:37:03 » |
|
Yo no me quedo con la parte entera de forma explícita.
Creo que lo que pasa es que lo hace automáticamente el lenguaje de programación cuando, una variable decimal de tipo float o double, la recogemos en otra variable de tipo int.
Ahora tengo prisa pero por la noche verifico si és así.
Otra aclaración sobre mi exposición anterior es que la variable valores[] lo que recoge es el numero de veces que salió el numero (entero).
|
|
|
|
|
En línea
|
Saludos
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #18 : Junio 05, 2006, 16:50:33 » |
|
Habría que ver lo que hace la función ésta aleatorio.NextDouble. Pero sí, tiene pinta de ser lo que tú dices.
Si tienes un generador de aleatorios doubles entre 0 y 1 quieres uno de enteros entre 0 y N, lo mejor es multiplicar por N+1 y quedarte con la parte entera. Para eso suele bastar con asigar a la variable entera que sirve de salida el valor (double) del número aleatorio obtenido.
|
|
|
|
|
En línea
|
|
|
|
JoanD
Usuario
Fotones: 1
Desconectado
Mensajes: 91
|
 |
« Respuesta #19 : Junio 06, 2006, 00:31:21 » |
|
El problema es que no sabia como quedarme con la parte entera ya que la función Round también me redondeaba hacia arriba o hacia abajo según si era superior o inferior a .5
Pero ya he averiguado como hacerlo en C#, se hace por medio de la función Floor y ya sale todo bién.
|
|
|
|
|
En línea
|
Saludos
|
|
|
Ontureño
Usuario
Fotones: 115
Desconectado
Mensajes: 3159
|
 |
« Respuesta #20 : Junio 06, 2006, 10:42:56 » |
|
Es raro eso. A ver, por ejemplo, si la variable r contiene un aletorio double entre 0 y 1, el código:
int n;
double r;
int N;
N=1000; //los números que quieras obtener
/*
Aquí cosas para obtener la variable r
*/
n = r * (N + 1) ;
Debería tobar la parte entera en la variable final n, nada de redondear por arriba  . No sé.
|
|
|
|
|
En línea
|
|
|
|
JoanD
Usuario
Fotones: 1
Desconectado
Mensajes: 91
|
 |
« Respuesta #21 : Junio 06, 2006, 20:49:09 » |
|
En C# si n es de tipo int, r de tipo double y N de tipo int me da error al hacer:
n = r * (N + 1) ;
para que no de error hay que hacer la conversión de r a int y ahí es donde me redondea (pero no a mi gusto).
Quizás en C no tengas ese problema pero sí en C#.
De todos modos, sabiendolo, se puede solucionar como dije anteriormente mediante la función Math.Floor
|
|
|
|
|
En línea
|
Saludos
|
|
|
|