2009-10-08 13 views
7

Esto puede parecer una pregunta extraña, pero ¿dónde puedo encontrar un generador de números aleatorios que funcione en C o C++ que no sea muy bueno?Crappy generador de números aleatorios

Contexto: Estoy creando un software de trazado de gráfico de árbol y lo pruebo usando números aleatorios de varios dígitos (por lo que cada dígito se convierte en un nodo en el árbol). El generador de números aleatorios que he estado usando, que es el que viene con el compilador C++ de GNU, me da una buena cantidad de valores. Eso está bien, pero quiero ver cómo se ve la tabla cuando los números se agrupan y son menos homogéneos.

¿Alguien puede sugerir un generador de números aleatorios que ha demostrado no ser tan aleatorio?

(¡Oh, cualquiera que vincule a xkcd y/o sugiera que acabo de devolver 4 recibirá sarcasmo en respuesta).

+6

Como no te gusta XKCD, puedes devolver 9: http://web.archive.org/web/20011027002011/http://dilbert.com/comics/dilbert/archive/images/dilbert2001182781025.gif –

+1

Necesita definir mejor su distribución esperada: por ejemplo, cualquier PRNG decente le dará una distribución no uniforme para 'rand()% 3' (debido al sesgo del módulo), pero dudo que eso satisfaga sus calificaciones. –

+0

¿Sobre qué rango? –

Respuesta

0

use srand, pero agregue una semilla, que no cambia mucho. de hecho, todos los generadores de números pseudoaleatorios se comportan de esta manera.

básicamente, simplemente siembra con 1, luego 2 y 3 ... muy pronto verás que los números "aleatorios" no son tan aleatorios.

+0

¿Está sugiriendo resembrar cada vez antes de obtener un nuevo número? – thornate

+0

sí ... si vuelves a sembrar cada vez, básicamente rompes el PRNG ya que solo genera el siguiente número. Si repites la semilla, empeora, generando el mismo número una y otra vez. –

0

En realidad, la función rand() es bastante mala. Yo uso GameRand, que es REALMENTE simple, y produce resultados decentes, pero puede que aún no sea lo suficientemente malo para ti.

+0

Depende. Creo que GCC/GLibc implementa 'rand()' con 'random()' y que su PRNG es bastante bueno. –

+0

Cita: http://www.gnu.org/s/libc/manual/html_node/BSD-Random.html#BSD-Random Cita: "No hay ninguna ventaja de usar estas funciones con la biblioteca GNU C; las apoyamos solo para compatibilidad con BSD ". Por lo tanto, cualquier dato que compare 'rand()' con 'random()' de BSD no se aplica a GLibc. –

1

A C solución ++:

class ClumpedRandom 
{ 
    public: 
    ClumpedRandom(int maxClumpSize) 
    : mMaxClump(maxClumpSize) 
    , mCurrentClumpSize(0) 
    , mCurrentCount(0) 
    { 
     if (!sInitialized) { 
     sInitialized = true; 
     srand(time(NULL)); 
     } 
    } 

    int operator()() 
    { 
     if (++mCurrentCount >= mCurrentClumpSize) { 
     // Need a new clump: 
     mCurrentClumpSize = rand() % mMaxClump; 
     mCurrentCount = 0; 
     mCurrentValue = rand(); 
     } 

     return mCurrentValue; 
    } 


    private: 
    static bool sInitialized; 
    int mMaxClump; 
    int mCurrentClumpSize; 
    int mCurrentCount; 
    int mCurrentValue; 
}; 

Produce carreras de longitud aleatoria de al mayoría de los casos maxClumpSize del mismo valor de número aleatorio. (No dije eso muy claro ... espero que entiendas la idea).

+0

¿Por qué no 'srand()' en su ctor? Podría tener una variable estática privada que le indique si ha llamado 'srand()' o no, y si no lo ha hecho, puede llamarlo. Es bastante simple (aunque si el usuario llama 'srand()' por su cuenta puede fallar). –

+1

@Chris: lo pensé, pero no es beneficioso para srand() 'más de una vez si hizo varios objetos de ClumpedRandom. En mi propio código, utilizaría un objeto PRNG con estado en lugar de srand()/rand() para asegurar flujos verdaderamente independientes. Parece que su aplicación en realidad no necesita preocuparse por la calidad de todos modos ... –

+0

@Chris: Oh, te he malinterpretado al principio. Claro, podríamos hacer eso ... editar próximamente ... –

7

Siempre he pensado en randu como el padrino de los malos generadores de números aleatorios.

+0

De acuerdo. Randu es un clásico. – Boojum

3

Implementar un bastante corto Linear Feedback Shift Register mediante el uso de la manipulación de bits en C.

La mayor parte del material publicado en LFSR se concentrará en secuencias máxima, pero suena como usted podría sabotear uno de estos para producir una secuencia más corta, con un poco de experimentación.

1

Una manera en la que puede introducir clustering mientras continúa usando gcc es tomar aleatoriamente dos de los números aleatorios devueltos como los corchetes superiores & para un número aleatorio de iteraciones. Hazlo unas cuantas veces y deberías obtener una agrupación aleatoria.

3

El Boost library el centro o funciones para generar valores aleatorios distribuidos en varias distribuciones no uniformes, incluyendo la distribución normal que podría generar árboles de formas interesantes.

2

El estándar C sugiere:

static unsigned long int next = 1; 

int rand(void) // RAND_MAX assumed to be 32767 
{ 
    next = next * 1103515245 + 12345; 
    return (unsigned int)(next/65536) % 32768; 
} 

void srand(unsigned int seed) 
{ 
    next = seed; 
} 

Como un simple generador de congruencia lineal (LCG), no es malo (hay muchos juegos peores de las constantes que puede utilizar), pero ciertamente no es una un buen generador de números pseudoaleatorios en comparación con otros miembros del universo de generadores de números pseudoaleatorios criptográficos y casi criptográficos. Puede ser suficientemente malo para usted o puede consultar el volumen 2 de Knuth para buscar otros conjuntos de números incorrectos. (Mi viejo) copia de Sedgewick (tiene una bastante corta el capítulo 35 de números aleatorios con algunos ejemplos de malas constantes.)

1

Tome un vistazo a esta función aleatoria:

http://xkcd.com/221/

+0

Creo que estaba pidiendo! Xkcd :) .. "(Oh, cualquiera que vincule a xkcd y/o sugiera que acabo de devolver 4 recibirá sarcasmo en respuesta)." – warren

+1

¡Muy cierto, así que dame mi "recibiré sarcasmo en respuesta"! Downmodding! = ¡Sarcasmo! – Rick

0

A menudo, para los números sospechosos de apariencia aleatoria, y generalmente necesito deterministas, calculo senos y cosenos de expresiones simples con valores de gran tamaño y modulación de fase. Normalmente estoy generación de colores en dos dimensiones con fines gráficos ("texturas de procedimiento" y todo eso) así que voy a dar un ejemplo de esa manera genérica en pseudocódigo:

for i=1,N 
    for j=1,N 
    value[i*n+j] = sin(51*i*i+cos(80*j)) + sin(300*j+3*sin(111*i-j)) 

Garantizado para fallar las pruebas más graves de aleatoriedad. Los resultados son malos de una manera que es útil para el arte.

Es divertido sentarse y jugar con fórmulas como estas en un entorno de trazado interactivo como Matlab o Python con numpy y matplotlib.

Cuestiones relacionadas