2016-04-24 11 views
6

Gdybym produkować zmiennoprzecinkowych w następujący sposób:Czy "minimalna do maksymalnej" jednolita dystrybucja rzeczywista wytworzy Inf, -Inf lub NaN?

template <typename T> 
T RandomFromRange(T low, T high){ 
    std::random_device random_device; 
    std::mt19937 engine{random_device()}; 
    std::uniform_real_distribution<T> dist(low, high); 
    return dist(engine); 
} 

template <typename T> 
T GetRandom(){ 
    return RandomFromRange 
    (std::numeric_limits<T>::min(),std::numeric_limits<T>::max()); 
} 

//produce floating point values: 
auto num1 = GetRandom<float>(); 
auto num2 = GetRandom<float>(); 
auto num3 = GetRandom<float>(); 
//... 

Czy to możliwe, że będę kiedykolwiek wrócić do NaN, Inf lub -Inf?

+1

Biorąc pod uwagę, że żadna z nich nie mieści się w zakresie [min, max], to prawdopodobnie nie. –

Odpowiedz

9

Rozważmy, co generuje std::uniform_real_distribution.

Generuje losowe wartości: i zmiennoprzecinkowych, równomiernie rozłożonych na przedziale [a, b)

Tak, to między std::numeric_limits<foat>::min() i std::numeric_limits<float>::max(), w tym były, ale z wyjątkiem ostatniego. Jakie wartości powracają te limity? Zwracają one odpowiednio: FLT_MIN i FLT_MAX. Co to jest?

minimalna znormalizowane dodatni zmiennoprzecinkową liczba

maksymalna zakodowania skończonej liczby zmiennoprzecinkowej

Ponieważ ani {dodatnie, ujemne} bez krawędzi ani NaN jest w zakresie liczb skończonych , nie, nie są generowane.

Jak podkreślił Christopher Oicles, należy zwrócić uwagę, że FLT_MIN i co za tym idzie, std::numeric_limits<foat>::min() jest najmniejszym pozytywny wartość reprezentowalna.

Jak podkreślił Christopher Dodd, jeśli zakres [min, max) przekracza std::numeric_limits<float>::max(), wtedy dostanie niezdefiniowanej zachowanie i w tym przypadku żadnego wyjścia, w tym generowania nieskończoność byłoby możliwe.

+1

Dla typów zmiennoprzecinkowych, 'std :: numeric_limits :: min()' jest wartością dodatnią (najmniejszą niezerową wartością dodatnią).I różnica: 'std :: numeric_limits :: max() - std :: numeric_limits :: min()' zwykle kończy się na 'std :: numeric_limits :: max()' (na pewno nie większe, w w każdym przypadku). Nie jestem więc pewien, czy Trevor wiedział o tym, czy nie, ale jego wybór zakresu udało się uniknąć nieokreślonego zachowania z dystrybucji. –

+0

@ ChristopherOicles, nie zdawałem sobie z tego sprawy. Włączyłem to w mojej odpowiedzi. – user2079303

6

Właściwie, to powoduje niezdefiniowanej zachowanie ze względu na wymagania dotyczące std::uniform_real_distribution (pkt 26.5.8.2.2 projektu specyfikacji mam):

explicit uniform_real_distribution(RealType a = 0.0, RealType b = 1.0); 
    Requires: a ≤ b and b − a ≤ numeric_limits<RealType>::max(). 
    Effects: Constructs a uniform_real_distribution object; a and b correspond to 
      the respective parameters of the distribution. 

Twój Konkretnym przykładem będzie przelewać że numeric_limits wymóg.

Teraz mógłby zbudować std::uniform_real_distribution<double> z std::numeric_limits<float>::min/max jak granice, a które powinny być dobrze zdefiniowane. Jest również prawdopodobne, że twój przykład będzie działał na większości implementacji (ponieważ generalnie promują one pływaki do podwójnych w wewnętrznych obliczeniach), ale wciąż uderza niezdefiniowane zachowanie.

Jeśli chodzi o implementacje, w których to nie działa, domyślam się, że najbardziej prawdopodobnym trybem awarii byłoby wygenerowanie Inf, ponieważ wygenerowałoby to b-a.

Powiązane problemy