uniform(0, 1)
dapat menghasilkan 0
, tetapi tidak akan pernah menghasilkan 1
.
The dokumentasi memberitahu Anda bahwa endpoint b
dapat dimasukkan dalam nilai-nilai yang dihasilkan:
Nilai titik akhir b
mungkin atau mungkin tidak termasuk dalam rentang tergantung pada pembulatan titik-mengambang dalam persamaan a + (b-a) * random()
.
Jadi untuk uniform(0, 1)
, formula 0 + (1-0) * random()
, disederhanakan 1 * random()
, harus mampu menghasilkan dengan 1
tepat. Itu hanya akan terjadi jika random.random()
1.0 exactly. However,
acak () *never* produces
1.0`.
Mengutip random.random()
dokumentasi :
Kembalikan nomor floating point acak berikutnya dalam kisaran [0,0, 1.0).
Notasi [..., ...)
berarti bahwa nilai pertama adalah bagian dari semua nilai yang mungkin, tetapi yang kedua tidak. random.random()
akan paling nilai produk sangat dekat dengan 1.0
. float
Jenis Python adalah nilai floating point IEEE 754 base64 , yang mengkodekan sejumlah fraksi biner (1/2, 1/4, 1/5, dll.) Yang membentuk nilai, dan nilai yang random.random()
dihasilkan hanyalah jumlah dari suatu pemilihan acak dari 53 fraksi tersebut dari 2 ** -1
(1/2) hingga 2 ** -53
(1/9007199254740992).
Namun, karena dapat menghasilkan nilai yang sangat dekat 1.0
, bersama dengan kesalahan pembulatan yang terjadi ketika Anda mengalikan nubmers floating point, Anda dapat menghasilkan b
untuk beberapa nilai a
dan b
. Tetapi 0
dan 1
tidak di antara nilai-nilai.
Catatan yang random.random()
dapat menghasilkan 0,0, jadi a
selalu termasuk dalam nilai yang mungkin untuk random.uniform()
( a + (b - a) * 0 == a
). Karena ada 2 ** 53
nilai berbeda yang random.random()
dapat menghasilkan (semua kemungkinan kombinasi dari 53 pecahan biner), hanya ada 2 ** 53
peluang 1 in (jadi 1 dalam 9007199254740992) yang pernah terjadi.
Jadi nilai tertinggi yang random.random()
dapat dihasilkan adalah 1 - (2 ** -53)
; cukup pilih nilai yang cukup kecil untuk b - a
memungkinkan pembulatan menendang ketika dikalikan dengan random.random()
nilai yang lebih tinggi . Semakin kecil b - a
, semakin besar kemungkinan hal itu terjadi:
>>> 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
Jika Anda menekan b = 0.0
, maka kami telah membagi 1023 kali, nilai di atas berarti kami beruntung setelah 1019 divisi. Nilai tertinggi yang saya temukan sejauh ini (menjalankan fungsi di atas dalam satu lingkaran dengan max()
) adalah 8.095e-320
(1008 divisi), tetapi mungkin ada nilai yang lebih tinggi. Ini semua adalah permainan kebetulan. :-)
Hal ini juga dapat terjadi jika tidak ada banyak langkah terpisah antara a
dan b
, seperti kapan a
dan b
memiliki eksponen yang tinggi dan mungkin tampak jauh lebih jauh. Nilai titik apung masih hanya perkiraan, dan jumlah nilai yang dapat dikodekannya terbatas. Misalnya, hanya ada 1 fraksi biner perbedaan antara sys.float_info.max
dan sys.float_info.max - (2 ** 970)
, sehingga ada kemungkinan 50-50 random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
menghasilkan 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)
, makaP(X=x)
adalah hampir pasti 0, untuk semua nilai x. (Ini karena ada banyak kemungkinan nilai dalam interval.) Jika Anda mencari tepat 0 atau 1, Anda harus menggunakan fungsi yang berbedarandom.choice