2009-10-08 15 views
7

Questa può sembrare una domanda strana, ma dove posso trovare un generatore di numeri casuali che funziona in C o C++ che non è molto buono?Crappy Random Number Generator

Contesto: Sto creando un grafico per tracciare un grafico ad albero e testarlo utilizzando numeri casuali a più cifre (quindi ogni cifra diventa un nodo nell'albero). Il generatore di numeri casuali che ho usato - che è quello che viene fornito con il compilatore GNU C++ - mi dà una bella diffusione di valori. Va bene, ma voglio vedere come appare la tabella quando i numeri si raggruppano e sono meno omogenei.

Qualcuno può suggerire un generatore di numeri casuali che ha dimostrato di non essere così casuale?

(Oh, tutti quelli che si collegano a xkcd e/o suggeriscono che ho appena restituito 4 riceveranno il sarcasmo in risposta).

+6

Dato che non ti piace XKCD, puoi restituire 9: http://web.archive.org/web/20011027002011/http://dilbert.com/comics/dilbert/archive/images/dilbert2001182781025.gif –

+1

È necessario definire meglio la distribuzione prevista: ad esempio, qualsiasi PRNG decente fornirà una distribuzione non uniforme per 'rand()% 3' (a causa del bias del modulo), ma dubito che soddisfi le tue qualifiche. –

+0

Oltre quale intervallo? –

risposta

0

usa srand, ma aggiungi un seme che non cambia molto. in effetti, tutti i generatori di numeri pseudo-casuali si comportano in questo modo.

in pratica, basta seminare con 1, quindi 2 poi 3 .. molto presto vedrai che i numeri "casuali" non sono così casuali.

+0

Stai suggerendo di ricomporre ogni volta prima di ottenere un nuovo numero? – thornate

+0

sì .. se si ri-semina ogni volta, si interrompe essenzialmente il PRNG poiché genera solo il numero successivo. Se ripeti il ​​seme, allora peggiora, generando lo stesso numero più e più volte. –

0

In realtà, la funzione rand() è davvero pessima. Io uso GameRand che è REALMENTE semplice, e produce risultati decenti, ma potrebbe non essere ancora abbastanza schifoso per te.

+0

Dipende. Credo che GCC/GLIBc implementa 'rand()' con 'random()' e che il loro PRNG sia in effetti piuttosto buono. –

+0

Citation: http://www.gnu.org/s/libc/manual/html_node/BSD-Random.html#BSD-Random Quote: "Non c'è alcun vantaggio nell'usare queste funzioni con la libreria GNU C, le supportiamo solo per compatibilità con BSD. " Quindi qualsiasi dato che mette a confronto 'rand()' in 'random()' di BSD non si applica a GLibc. –

1

Una soluzione C++:

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 casuali funzionamenti lunghezza pari maggior parte dei casi maxClumpSize dello stesso valore numero casuale. (Non l'ho detto molto chiaramente ... spero che tu abbia capito l'idea).

+0

Perché non si 'srand()' nel tuo ctor? Potresti avere una variabile statica privata che ti dice se hai chiamato 'srand()' o no, e se non lo hai puoi chiamarlo. È abbastanza semplice (anche se il tuo utente chiama 'srand()' da solo potrebbe non riuscire). –

+1

@Chris: ci ho pensato, ma non c'è alcun vantaggio a srand() di più di una volta se ha creato più oggetti ClumpedRandom. Nel mio codice userei un oggetto PRNG stateful piuttosto che srand()/rand() per assicurare flussi veramente indipendenti. Sembra che la sua applicazione non abbia davvero bisogno di preoccuparsi per la qualità, ma comunque ... –

+0

@Chris: Oh, ho letto male in un primo momento. Certo, potremmo farlo ... modifica imminente ... –

7

Ho sempre pensato a randu come padrino di generatori di numeri casuali sbagliati.

+0

Concordato. Randu è un classico. – Boojum

3

implementare una abbastanza breve Linear Feedback Shift Register utilizzando manipolazione dei bit in C.

La maggior parte del materiale pubblicato su LFSR si concentrerà su sequenze massimali, ma suona come si potrebbe sabotare uno di questi per produrre una sequenza più corta, con un po 'di sperimentazione

1

Un modo in cui è possibile introdurre il cluster continuando a utilizzare gcc consiste nel prendere casualmente due numeri casuali restituiti come le parentesi superiori & inferiori per un numero casuale di iterazioni. Fatelo alcune volte e dovreste ottenere clustering casuali.

3

Il Boost library offre funzioni per generare valori casuali distribuite su varie distribuzioni non uniformi, compresa la distribuzione normale che potrebbe generare alberi sagomati interessanti.

2

Lo standard C suggerisce:

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; 
} 

Come un semplice generatore di congruenziale lineare (LCG), ma non è male (ci sono molti set peggiori di costanti è possibile utilizzare), ma non è certamente un buon generatore di numeri pseudo-casuali rispetto ad altri membri dell'universo di generatori di numeri pseudo-casuali crittografici e quasi crittografici. Potrebbe essere abbastanza brutto per te, oppure potresti consultare il volume di Knuth 2 per cercare altri set di numeri errati. (Il mio (vecchio) copia di Sedgewick ha una piuttosto breve capitolo 35 sulla numeri casuali con alcune illustrazioni di costanti cattivi.)

1

Date un'occhiata a questa funzione random:

http://xkcd.com/221/

+0

Credo che stava chiedendo! Xkcd :) .. "(Oh, tutti quelli che si collegano a xkcd e/o suggeriscono che ho appena restituito 4 riceveranno il sarcasmo in risposta)." – warren

+1

Così vero, quindi dammi il mio "otterrà sarcasmo in risposta"! Downmodding! = Sarcasmo! – Rick

0

Spesso per numeri casuali dall'aspetto casuale e di solito ho bisogno di deterministici, calcolo seni e coseni di espressioni semplici con valori di grandi dimensioni e modulazione di fase. In genere sto generando i colori in due dimensioni per usi grafici ("texture procedurali" e tutto ciò che) quindi mi dare un esempio del genere in pseudocodice generico:

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)) 

garantito per non riuscire più gravi prove di casualità. I risultati sono schifosi in un modo che è utile per l'arte.

È divertente sedersi e giocare con formule come queste in un ambiente di plottaggio interattivo come Matlab o Python con numpy e matplotlib.