在the documentation中,据说uniform(0,1)
可以生成值0
和1
。
我已经运行uniform(0, 1)
10000次,但从未产生过零。即使是uniform(0, 0.001)
。
random.uniform(0,1)
会产生0
或1
吗?
答案 0 :(得分:13)
uniform(0, 1)
可以产生0
,但它永远不会产生1
。
documentation告诉您,端点b
可以包含在生成的值中:
取决于等式
b
中的浮点舍入,端点值a + (b-a) * random()
可能包含也可能不包含在范围内。
因此,对于uniform(0, 1)
,公式0 + (1-0) * random()
(简化为1 * random()
)必须能够精确生成1
。仅当random.random()
为1.0 exactly. However,
random()*never* produces
1.0`时才会发生这种情况。
引用random.random()
documentation:
返回[0.0,1.0)范围内的下一个随机浮点数。
符号[..., ...)
表示第一个值是所有可能值的一部分,而第二个则不是。 random.random()
最多会产生与1.0
非常接近的值。 Python的float
类型是IEEE 754 base64 floating point value,它编码构成值的许多二进制分数(1 / 2、1 / 4、1 / 5等) ,而random.random()
产生的值只是从2 ** -1
(1/2)到2 ** -53
(1/9007199254740992)这53个这样的分数中随机选择的总和。
但是,由于它可以产生非常接近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 ** 53
中只有1的概率(因此9007199254740992中为1)发生。
因此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
的指数很高时,可能看起来像是远appart。浮点值仍然仅仅是近似值,它们可以编码的值的数量是有限的。例如,sys.float_info.max
和sys.float_info.max - (2 ** 970)
之间只有1个二进制差值,因此random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
产生sys.float_info.max
的机会为50-50:
>>> 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
答案 1 :(得分:5)
“多次”是不够的。 10,000还不够。 CKQuerySubscription
从2 ^ 53(9,007,199,254,740,992)个不同的值中进行选择。您对其中的两个有兴趣。因此,您应该期望生成几个 quadrillion 随机值,然后再获取正好为0或1的值。所以有可能,但是很有可能永远不会观察到它。
答案 2 :(得分:1)
好的。尝试使用uniform(0, 0.001)
可以使您步入正轨。只需保持足够的边界以使其早日发生。
>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
0.0
答案 3 :(得分:1)
您可以尝试生成一个循环,该循环计算要显示为精确的0(不显示)所需的迭代次数。
此外,正如霍布斯所说,uniformly
被采样的值的数量为9,007,199,254,740,992。这意味着看到0的概率恰好是1 / 9,007,199,254,740,992。一般来说,四舍五入意味着您将需要在 平均值 个样本中找到10个四万亿像素。当然,您可能会在前10次尝试中找到它,或者永远不会。
不可能对1进行采样,因为为值定义的间隔用括号括起来,因此不包括1。