Supponiamo di voler utilizzare le funzionalità C ++ <random>in un programma pratico (per alcune definizioni di "pratico" - i vincoli qui fanno parte di questa domanda). Il codice è approssimativamente simile a questo:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
La mia domanda è: per quale tipo dovresti usare ENGINE?
Lo dicevo sempre
std::mt19937perché era veloce digitare e aveva il riconoscimento del nome. Ma in questi giorni sembra che tutti stiano dicendo che il Mersenne Twister è molto pesante e ostile alla cache e non supera nemmeno tutti i test statistici che altri fanno.Vorrei dire
std::default_random_engineperché è l'ovvio "default". Ma non so se varia da piattaforma a piattaforma e non so se sia statisticamente utile.Dal momento che ognuno è su una piattaforma a 64-bit in questi giorni, dovremmo almeno essere utilizzando
std::mt19937_64overstd::mt19937?Vorrei dirlo
pcg64oxoroshiro128perché sembrano rispettati e leggeri, ma non esistono<random>affatto.Io non so niente di
minstd_rand,minstd_rand0,ranlux24,knuth_b, ecc - di certo si deve essere buono per qualcosa?
Ovviamente ci sono alcuni vincoli concorrenti qui.
Forza del motore (
<random>non ha PRNG crittograficamente forti, ma alcuni di quelli standardizzati sono "più deboli" di altri, giusto?)sizeofil motore.La sua velocità
operator().Facilità di semina.
mt19937è notoriamente difficile seminare correttamente perché ha così tanto stato da inizializzare.Portabilità tra i fornitori di biblioteche. Se un fornitore
foo_engineproduce numeri diversi da quelli di un altro fornitorefoo_engine, ciò non va bene per alcune applicazioni. (Speriamo che questo non escluda nulla tranne forsedefault_random_engine.)
Pesando tutti questi vincoli nel miglior modo possibile, quale diresti sia la migliore risposta "best practice restando all'interno della libreria standard"? Devo continuare a usare std::mt19937o cosa?