2016-04-24 7 views
6

Wenn ich in der folgenden Art und Weise Gleitkomma-Werte erzeugen:Wird "min bis max" uniforme echte Verteilung Inf, -Inf oder NaN erzeugen?

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>(); 
//... 

Ist es möglich, dass ich jemals ein NaN zurück, Inf oder -Inf?

+1

Da keiner von denen in den Bereich [min, max] fällt, dann vermutlich nicht. –

Antwort

9

Lassen Sie uns in Betracht ziehen, was std::uniform_real_distribution erzeugt.

Erzeugt zufällig Gleitkommawerte i, gleichmäßig verteilt auf dem Intervall [a, b)

So, das zwischen std::numeric_limits<foat>::min() und std::numeric_limits<float>::max(), einschließlich früheren, aber ohne letzteren. Nach welchen Werten kehren diese Grenzen zurück? Sie geben FLT_MIN bzw. FLT_MAX zurück. Nun, was sind das?

minimale normalisierte positive Gleitkommazahl

maximal darstellbar finite Gleitkommazahl

Da weder {positiver, negativer} infinity, noch NaN im Bereich der endlichen Zahlen Nein, sie werden nicht generiert.

Wie von Christopher Oicles darauf achtet, dass FLT_MIN und durch die Erweiterung, std::numeric_limits<foat>::min() ist der kleinste positive darstellbare Wert.

Wie von Chris Dodd, wenn der Bereich von [min, max)std::numeric_limits<float>::max() überschreitet, dann würden Sie nicht definiertes Verhalten bekommen und in diesem Fall eine Ausgabe, Erzeugen Unendlichkeit einschließlich möglich wäre.

+1

Für Fließkommatypen ist 'std :: numeric_limits :: min()' ein positiver Wert (der kleinste von Null verschiedene positive Wert).Und der Unterschied: 'std :: numeric_limits :: max() - std :: numeric_limits :: min()' endet normalerweise gleich 'std :: numeric_limits :: max()' (sicherlich nicht größer, in auf jeden Fall). Ich bin mir also nicht sicher, ob Trevor davon wusste oder nicht, aber mit seiner Range-Wahl gelang es, ein undefiniertes Verhalten der Distribution zu vermeiden. –

+0

@ChristopherOicles guter Punkt, das hatte ich nicht bemerkt. Ich habe das in meine Antwort aufgenommen. – user2079303

6

Eigentlich verursacht dies nicht definiertes Verhalten, aufgrund der Anforderungen für std::uniform_real_distribution (Abschnitt 26.5.8.2.2 des Entwurfs spec ich habe):

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. 

Ihr konkretes Beispiel, dass numeric_limits Anforderung überlaufen. Jetzt

Sie konnte bauen eine std::uniform_real_distribution<double> mit std::numeric_limits<float>::min/max als die Grenzen, und das sollte gut definiert. Es ist auch wahrscheinlich, dass Ihr Beispiel bei den meisten Implementierungen funktioniert (da Floats in internen Berechnungen normalerweise verdoppelt werden), aber es trifft immer noch auf undefiniertes Verhalten.

Auf Implementierungen, wo es nicht funktioniert, würde ich raten, dass der wahrscheinlichste Fehlermodus Inf erzeugen würde, wie das b-a erzeugen würde.