2013-04-25 10 views
9

C++ 11 std :: uniform_real_distribution (-1, 1) fornisce numeri nell'intervallo [-1,1).std :: uniform_real_distribution range compreso

Come si ottiene una distribuzione reale uniforme nell'intervallo [-1,1]?

Praticamente non importa, ma logicamente sto provando a selezionare un valore nell'intervallo compreso.

risposta

14

Questo è più facile da pensare se si inizia guardando i numeri interi. Se passi [-1, 1) ti aspetteresti di ottenere -1, 0. Poiché desideri includere 1, devi passare [-1, (1 + 1)) o [-1, 2). Ora ottieni -1, 0, 1.

si vuole fare la stessa cosa, ma con i doppi:

prestito da this answer:

#include <cfloat> // DBL_MAX 
#include <cmath> // std::nextafter 
#include <random> 
#include <iostream> 

int main() 
{ 
    const double start = -1.0; 
    const double stop = 1.0; 

    std::random_device rd; 
    std::mt19937 gen(rd()); 

    // Note: uniform_real_distribution does [start, stop), 
    // but we want to do [start, stop]. 
    // Pass the next largest value instead. 
    std::uniform_real_distribution<> dis(start, std::nextafter(stop, DBL_MAX)); 

    for (auto i = 0; i < 100; ++i) 
    { 
    std::cout << dis(gen) << "\n"; 
    } 
    std::cout << std::endl; 
} 

(vedere il codice run here)

Cioè, trovare il prossimo grande doppia valore dopo quello che vuoi, e passa invece come valore finale.

+1

Meraviglioso, grazie. VS2012 non sembra avere questa funzione, ma fortunatamente boost lo ha in [math toolkit] (http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/ next_float/nextafter.html) –

+0

Le distribuzioni a virgola mobile standard non forniscono la precisione fino all'ultima cifra di precisione, ma soffrono invece di problemi di arrotondamento, il che significa che non è appropriato provare a utilizzarle in questo modo. – bames53

1

Sfortunatamente le effettive implementazioni delle distribuzioni in virgola mobile non consentono di essere così precisi. Ad esempio, uniform_real_distribution<float> dovrebbe produrre valori in un dato intervallo di metà, ma a causa di problemi di arrotondamento potrebbe invece produrre valori in un intervallo inclusivo.

Here's un esempio del problema con generate_cannonical e problemi simili si verificano con le altre real_distributions.