uniform(0, 1)
có thể sản xuất 0
, nhưng nó sẽ không bao giờ sản xuất 1
.
Các tài liệu hướng dẫn cho bạn biết rằng thiết bị đầu cuối b
có thể được bao gồm trong giá trị sản xuất:
Giá trị điểm cuối b
có thể có hoặc không được bao gồm trong phạm vi tùy thuộc vào làm tròn điểm nổi trong phương trình a + (b-a) * random()
.
Vì vậy uniform(0, 1)
, công thức 0 + (1-0) * random()
, được đơn giản hóa 1 * random()
, sẽ phải có khả năng sản xuất 1
chính xác. Điều đó sẽ chỉ xảy ra nếu random.random()
là 1.0 exactly. However,
ngẫu nhiên () *never* produces
1.0`.
Trích dẫn random.random()
tài liệu :
Trả về số dấu phẩy động ngẫu nhiên tiếp theo trong phạm vi [0,0, 1,0).
Ký hiệu [..., ...)
có nghĩa là giá trị đầu tiên là một phần của tất cả các giá trị có thể, nhưng giá trị thứ hai thì không. random.random()
nhiều nhất sẽ tạo ra các giá trị rất gần với 1.0
. float
Kiểu của Python là một giá trị dấu phẩy động cơ sở của IEEE 754 , mã hóa một số phân số nhị phân (1/2, 1/4, 1/5, v.v.) tạo nên giá trị và giá trị random.random()
tạo ra chỉ đơn giản là tổng của một lựa chọn ngẫu nhiên 53 phân số như vậy từ 2 ** -1
(1/2) đến 2 ** -53
(1/9007199254740992).
Tuy nhiên, bởi vì nó có thể tạo ra giá trị rất gần 1.0
, cùng với làm tròn lỗi xảy ra khi bạn nhân nổi nubmers điểm, bạn có thể tạo ra b
cho một số giá trị của a
và b
. Nhưng0
và 1
không nằm trong số những giá trị đó.
Lưu ý rằng random.random()
có thể tạo 0,0, vì vậy a
luôn được bao gồm trong các giá trị có thể cho random.uniform()
( a + (b - a) * 0 == a
). Bởi vì có 2 ** 53
các giá trị khác nhau random.random()
có thể tạo ra (tất cả các kết hợp có thể có của 53 phân số nhị phân đó), chỉ có 1 trong2 ** 53
(vì vậy 1 trong 9007199254740992) có thể xảy ra.
Vì vậy, giá trị cao nhất có random.random()
thể có thể tạo ra là 1 - (2 ** -53)
; chỉ cần chọn một giá trị đủ nhỏ b - a
để cho phép làm tròn để khởi động khi nhân với random.random()
giá trị cao hơn . Càng nhỏ b - a
, cơ hội xảy ra càng lớn:
>>> 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
Nếu bạn trúng b = 0.0
, thì chúng tôi đã chia 1023 lần, giá trị trên có nghĩa là chúng tôi đã gặp may sau 1019 đơn vị. Giá trị cao nhất tôi tìm thấy cho đến nay (chạy hàm trên trong một vòng lặp với max()
) là8.095e-320
(1008 đơn vị), nhưng có thể có giá trị cao hơn. Tất cả đều là trò chơi may rủi. :-)
Nó cũng có thể xảy ra nếu không có nhiều bước riêng biệt giữa a
và b
, như khi nào a
và b
có số mũ cao và do đó có thể xuất hiện xa. Các giá trị dấu phẩy động vẫn chỉ là xấp xỉ và số lượng giá trị chúng có thể mã hóa là hữu hạn. Ví dụ: chỉ có 1 phần nhị phân khác biệt giữa sys.float_info.max
và sys.float_info.max - (2 ** 970)
, do đó, có 50-50 cơ hội random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
tạo ra 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)
, thìP(X=x)
là gần như chắc chắn 0, cho tất cả các giá trị của x. (Điều này là do có vô số giá trị có thể có trong khoảng.) Nếu bạn đang tìm kiếm chính xác 0 hoặc 1, bạn nên sử dụng một hàm khácrandom.choice