2012-12-23 22 views
18

Devo generare numeri casuali, ma da un intervallo il più ampio possibile (almeno 64 bit). Non mi interessa se la distribuzione è perfetta, quindi std::rand() funzionerebbe, ma restituisce solo uno int. Capisco che C++ 11 ha alcune capacità di generazione di numeri casuali che possono dare qualsiasi numero di dimensioni, ma è molto complesso da usare. Qualcuno può pubblicare un semplice esempio su come usarlo nel modo più semplice possibile per ottenere la funzionalità descritta (64 bit o più numeri casuali) nel modo più semplice possibile (come std::rand())?C++ 11 numeri casuali

risposta

30

Questo è come usare il C++ 11 generazione di numeri casuali per questo scopo (regolata da http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution):

#include <random> 
#include <iostream> 
int main() 
{ 
    /* Initialise. Do this once (not for every 
    random number). */ 
    std::random_device rd; 
    std::mt19937_64 gen(rd()); 

    /* This is where you define the number generator for unsigned long long: */ 
    std::uniform_int_distribution<unsigned long long> dis; 

    /* A few random numbers: */  
    for (int n=0; n<10; ++n) 
    std::cout << dis(gen) << ' '; 
    std::cout << std::endl; 
    return 0; 
} 

Invece di unsigned long long, è possibile utilizzare std::uintmax_t da cstdint per ottenere la più vasta gamma possibile intero (senza usare una vera libreria big-integer).

+1

Questo è molto buono per quasi tutti gli usi, ma si noti che fornisce solo 'sizeof (unsigned)' byte di entropia per il seme. Se hai bisogno di più, è possibile passare un ['std :: seed_seq'] (http://en.cppreference.com/w/cpp/numeric/random/seed_seq) nel costruttore di' mt19937' per passare quanti byte casuali vuoi. –

4

Non C++ 11, ma abbastanza facile

((unsigned long long)rand() << 32) + rand() Qui si generano due parti del Int64 come di

Come JasonD sottolineato, si presume che rand() generano 32 bit integer int32. E 'impercettibile xor rand() << x, rand() << (2*x), rand() << (3*x), ecc., Dove x < = bit in generazione da numero rand()`. Va anche bene.

+12

Presuppone che rand() restituisca effettivamente un numero a 32 bit. È probabile che solo 31 bit, se non è 15 bit. – JasonD

+1

@JasonD Sì, @RiaD dovrebbe controllare 'RAND_MAX' per determinare ciò. –

+0

Sotto Microsoft cl, fino al 19.x corrente, 'RAND_MAX' è 0x7FFF o 15 bit. – kkm

12

Si potrebbe facilmente avvolgere un motore generatore di numeri casuali in srand/metodi rand simile come questo:

#include <random> 
#include <iostream> 

struct MT19937 { 
private: 
    static std::mt19937_64 rng; 
public: 
    // This is equivalent to srand(). 
    static void seed(uint64_t new_seed = std::mt19937_64::default_seed) { 
     rng.seed(new_seed); 
    } 

    // This is equivalent to rand(). 
    static uint64_t get() { 
     return rng(); 
    } 
}; 

std::mt19937_64 MT19937::rng; 


int main() { 
    MT19937::seed(/*put your seed here*/); 

    for (int i = 0; i < 10; ++ i) 
     std::cout << MT19937::get() << std::endl; 
} 

(come srand e rand, questa implementazione non si preoccupa di thread-safe.)

Bene, le funzioni del wrapper sono così banali che è possibile utilizzare direttamente il motore.

#include <random> 
#include <iostream> 

static std::mt19937_64 rng; 

int main() { 
    rng.seed(/*put your seed here*/); 

    for (int i = 0; i < 10; ++ i) 
     std::cout << rng() << std::endl; 
} 
+2

Sfortunatamente, 'std :: mt19937_64 :: default_seed' è standardizzato come' 5489u', quindi i tuoi programmi di esempio produrranno sempre la stessa sequenza di output. –

+4

@JeffreyYasskin: Sì. Proprio come in 'srand()', è necessario fornire il proprio seme per ottenere una sequenza casuale distinta. – kennytm