uniform(0, 1)
kann produzieren 0
, aber es wird nie produzieren 1
.
Die Dokumentation sagt Ihnen , dass der Endpunkt b
könnte in den Werten erzeugt aufgenommen werden:
Der Endpunktwert b
kann abhängig von der Gleitkomma-Rundung in der Gleichung in dem Bereich enthalten sein oder nicht a + (b-a) * random()
.
Denn uniform(0, 1)
die Formel 0 + (1-0) * random()
, vereinfacht auf 1 * random()
, müsste in der Lage sein, 1
genau zu produzieren . Das würde nur passieren, wenn random.random()
1.0 exactly. However,
random () *never* produces
1.0` ist.
Zitieren der random.random()
Dokumentation :
Gibt die nächste zufällige Gleitkommazahl im Bereich [0.0, 1.0] zurück.
Die Notation [..., ...)
bedeutet, dass der erste Wert Teil aller möglichen Werte ist, der zweite jedoch nicht. random.random()
wird höchstens Werte sehr nahe an erzeugen 1.0
. Pythons float
Typ ist ein IEEE 754 base64-Gleitkommawert , der eine Anzahl von binären Brüchen (1/2, 1/4, 1/5 usw.) codiert , aus denen der Wert besteht, und der erzeugte Wert random.random()
ist einfach die Summe von a zufällige Auswahl dieser 53 solcher Fraktionen von 2 ** -1
(1/2) bis 2 ** -53
(1/9007199254740992).
Da es jedoch Werte sehr nahe produzieren kann 1.0
, zusammen mit Rundungsfehlern , die auftreten , wenn Sie mehrfach Punkt nubmers schwimmen, Sie können produzieren b
für einige Werte von a
und b
. Aber 0
und 1
gehören nicht zu diesen Werten.
Beachten Sie, dass random.random()
dies 0,0 erzeugen kann und daher a
immer in den möglichen Werten für random.uniform()
( a + (b - a) * 0 == a
) enthalten ist. Da es 2 ** 53
unterschiedliche Werte gibt, random.random()
die erzeugen können (alle möglichen Kombinationen dieser 53 binären Brüche), gibt es nur eine 1-in- 2 ** 53
Chance (also 1 in 9007199254740992), dass dies jemals passiert.
Der höchstmögliche Wert, der erzeugt werden random.random()
kann, ist also 1 - (2 ** -53)
: Wählen Sie einfach einen Wert, der klein genug ist b - a
, damit die Rundung einsetzt, wenn sie mit höheren random.random()
Werten multipliziert wird . Je kleiner b - a
ist, desto größer ist die Wahrscheinlichkeit, dass dies geschieht:
>>> import random, sys
>>> def find_b():
... a, b = 0, sys.float_info.epsilon
... while random.uniform(a, b) != b:
... b /= 2
... else:
... return b
...
>>> print("uniform(0, {0}) == {0}".format(find_b()))
...
uniform(0, 4e-323) == 4e-323
Wenn Sie treffen b = 0.0
, haben wir 1023 Mal geteilt. Der obige Wert bedeutet, dass wir nach 1019 Teilungen Glück hatten. Der höchste Wert, den ich bisher gefunden habe (Ausführen der obigen Funktion in einer Schleife mit max()
), ist 8.095e-320
(1008 Teilungen), aber es gibt wahrscheinlich höhere Werte. Es ist alles ein Glücksspiel. :-)
Es kann auch passieren, wenn es nicht viele diskrete Schritte zwischen a
und gibt b
, wie wenn a
und b
einen hohen Exponenten haben und daher weit auseinander liegen. Gleitkommawerte sind immer noch nur Näherungswerte, und die Anzahl der Werte, die sie codieren können, ist endlich. Zum Beispiel gibt es nur 1 binären Bruchteil der Differenz zwischen sys.float_info.max
und sys.float_info.max - (2 ** 970)
, so dass eine 50-50-Chance random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
ergibt sys.float_info.max
:
>>> a, b = sys.float_info.max - (2 ** 970), sys.float_info.max
>>> values = [random.uniform(a, b) for _ in range(10000)]
>>> values.count(sys.float_info.max) # should be roughly 5000
4997
X ~ U(0,1)
, dann dasP(X=x)
ist fast sicher 0, für alle Werte von x. (Dies liegt daran, dass das Intervall unendlich viele mögliche Werte enthält.) Wenn Sie genau 0 oder 1 suchen, sollten Sie eine andere Funktion verwenden - zum Beispielrandom.choice