uniform(0, 1)może produkować 0, ale nigdy nie będzie produkować 1.
Dokumentacja mówi, że punkt końcowy b mógł być włączone do wartości wytworzonych:
Wartość punktu końcowego bmoże, ale nie musi być zawarta w zakresie, w zależności od zaokrąglenia zmiennoprzecinkowego w równaniu a + (b-a) * random().
Tak więc uniform(0, 1), w 0 + (1-0) * random()uproszczeniu, formuła 1 * random()musiałaby być w stanie wytworzyć 1dokładnie. To by się stało tylko, jeśli random.random()jest 1.0 exactly. However,losowo () *never* produces1.0`.
Cytując random.random()dokumentację :
Zwraca kolejną losową liczbę zmiennoprzecinkową z zakresu [0,0, 1,0).
Notacja [..., ...)oznacza, że pierwsza wartość jest częścią wszystkich możliwych wartości, ale druga nie. random.random()co najwyżej wytworzy wartości bardzo zbliżone do 1.0. floatTyp Pythona to zmiennoprzecinkowa wartość IEEE 754 base64 , która koduje pewną liczbę ułamków binarnych (1/2, 1/4, 1/5 itd.) , Które składają się na wartość, a random.random()wytworzona wartość jest po prostu sumą losowy wybór tych 53 takich frakcji od 2 ** -1(1/2) do 2 ** -53(1/9007199254740992).
Jednakże, ponieważ może wytwarzać wartości bardzo blisko 1.0, razem z zaokrąglenia błędy występujące podczas pomnożyć pływających nubmers momencie, może produkować bdla pewnych wartości ai b. Ale 0i 1nie należą do tych wartości.
Zauważ, że random.random() może produkować 0,0, więc ajest zawsze uwzględniany w możliwych wartościach dla random.uniform()( a + (b - a) * 0 == a). Ponieważ istnieją 2 ** 53różne wartości, które random.random()mogą wytworzyć (wszystkie możliwe kombinacje tych 53 ułamków binarnych), istnieje tylko 1 na 1 2 ** 53(a więc 1 na 9007199254740992) szansa na takie zdarzenie.
Zatem najwyższą możliwą wartością, jaką random.random()można wytworzyć, jest 1 - (2 ** -53); po prostu wybierz wystarczająco małą wartość, b - aaby umożliwić zaokrąglanie, gdy zostanie pomnożone przez wyższe random.random()wartości. Im mniejsze b - a, tym większe są szanse, że się to wydarzy:
>>> 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
Jeśli trafisz b = 0.0, podzieliliśmy 1023 razy, powyższa wartość oznacza, że mieliśmy szczęście po 1019 dywizjach. Najwyższą wartością, jaką do tej pory znalazłem (uruchamianie powyższej funkcji w pętli z max()) jest 8.095e-320(1008 działów), ale prawdopodobnie są wyższe wartości. To gra losowa. :-)
Może się to również zdarzyć, jeśli nie ma wielu dyskretnych kroków pomiędzy ai b, na przykład kiedy ai bmają wysoki wykładnik, a więc może wydawać się dalekie. Wartości zmiennoprzecinkowe są nadal jedynie przybliżeniami, a liczba wartości, które mogą kodować, jest skończona. Na przykład, istnieje tylko 1 binarna część różnicy między sys.float_info.maxi sys.float_info.max - (2 ** 970), więc istnieje szansa 50-50 random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)produkuje 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),P(X=x)to prawie na pewno 0, dla wszystkich wartości x. (Jest tak, ponieważ w przedziale jest nieskończenie wiele możliwych wartości.) Jeśli szukasz dokładnie 0 lub 1, powinieneś użyć innej funkcji - na przykładrandom.choice