uniform(0, 1)може виробляти 0, але вона ніколи не виробляє 1.
Документація говорить вам , що кінцева точка b може бути включена в значеннях , отриманих:
Значення кінцевої точки bможе або не може бути включене в діапазон залежно від округлення з плаваючою комою в рівнянні a + (b-a) * random().
Отже uniform(0, 1), формула 0 + (1-0) * random(), спрощена до 1 * random(), повинна була б мати можливість 1точно виробляти . Це відбудеться лише за випадкових random.random()1,0 exactly. However,() *never* produces1,0 ".
Цитування random.random()документації :
Повертаємо наступне випадкове число з плаваючою комою в діапазоні [0,0, 1,0).
Позначення [..., ...)означає, що перше значення є частиною всіх можливих значень, а друге - ні. random.random()принаймні дасть величини, дуже близькі до 1.0. floatТип Python являє собою IEEE 754 base64 з плаваючою точкою , яке кодує ряд двійкових дробів (1/2, 1/4, 1/5 тощо), які складають значення, а значення random.random()виробляє просто суму a випадковий вибір цих 53 таких фракцій від 2 ** -1(1/2) до 2 ** -53(1/9007199254740992).
Однак, оскільки він може створювати значення, близькі до цього 1.0, разом з помилками округлення, які виникають при множенні нумерів з плаваючою комою, ви можете створювати bдля деяких значень aта b. Але 0і 1не є серед цих цінностей.
Зауважте, що random.random() може давати 0,0, тому aзавжди включається до можливих значень для random.uniform()( a + (b - a) * 0 == a). Оскільки є 2 ** 53різні значення, які random.random()можуть отримати (всі можливі комбінації з цих 53 двійкових дробів), є лише 2 ** 531 дюйм (тобто 1 на 9007199254740992) шанс, що коли-небудь трапиться.
Отже, найвища можлива цінність, яку random.random()може дати 1 - (2 ** -53); просто виберіть достатньо мале значення, b - aщоб дозволити закруглення, коли помножити на більш високі random.random()значення. Чим менше b - a, тим більше шанси на те, що станеться:
>>> 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
Якщо ви потрапили b = 0.0, то ми розділили 1023 рази, вище значення означає, що нам пощастило після 1019 поділів. Найвище значення, яке я знайшов поки що (запускаючи вищевказану функцію в циклі max()), є 8.095e-320(1008 поділів), але, ймовірно, є більш високі значення. Все це гра в шанс. :-)
Це також може статися, якщо між aта b, як, коли, aі bвисокий показник , не так багато дискретних кроків, і , можливо, це може здатися далеко. Значення з плаваючою комою залишаються лише наближеннями, а кількість значень, які вони можуть кодувати, є кінцевим. Наприклад, існує тільки одна двійковий дріб різниця між sys.float_info.maxі sys.float_info.max - (2 ** 970), таким чином є шанс , 50-50 random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)виробляє 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)це майже напевно 0, для всіх значень х. (Це тому, що в інтервалі є нескінченно багато можливих значень.) Якщо ви шукаєте рівно 0 або 1, вам слід скористатися іншою функцією, наприкладrandom.choice