在文档中,据说uniform(0,1)
可以生成值0
和1
。
我已经运行了uniform(0, 1)
10000次,但从未产生过零。即使在uniform(0, 0.001)
。
能否random.uniform(0,1)
产生0
或1
?
random.uniform
?
Math.random()
在JavaScript的作品,例如)。
random.uniform(0, 1)
在第一次调用返回一个0
在文档中,据说uniform(0,1)
可以生成值0
和1
。
我已经运行了uniform(0, 1)
10000次,但从未产生过零。即使在uniform(0, 0.001)
。
能否random.uniform(0,1)
产生0
或1
?
random.uniform
?
Math.random()
在JavaScript的作品,例如)。
random.uniform(0, 1)
在第一次调用返回一个0
Answers:
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,
random()1.0时才会发生这种情况*never* produces
。
返回范围为[0.0,1.0)的下一个随机浮点数。
该符号[..., ...)
表示第一个值是所有可能值的一部分,而第二个则不是。random.random()
在大多数生产值将非常接近到1.0
。Python的float
类型是IEEE 754 base64浮点值,该值对组成该值的许多二进制分数(1 / 2、1 / 4、1 / 5等)进行编码,并且该值random.random()
产生的只是a的和从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
具有较高的指数,也似乎相去甚远),也会发生这种情况。浮点值仍然仅仅是近似值,它们可以编码的值的数量是有限的。例如,sys.float_info.max
和之间只有1个二进制分数的差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
“几次”是不够的。10,000还不够。random.uniform
从2 ^ 53(9,007,199,254,740,992)个不同的值中选择。您对其中两个感兴趣。这样,您应该期望在获得恰好为0或1的值之前先生成几个四千万个随机值。
uniform(0, 1)
它是不可能产生1
的结果。这是因为该函数只是定义为def uniform(a, b): return a + (b - a) * random()
并且random()
永远不会产生1.0
。
您可以尝试生成一个循环,该循环计算要显示为精确的0(不显示)所需的迭代次数。
此外,正如霍布斯所说,所uniformly
采样的值的数量为9,007,199,254,740,992。这意味着看到0的概率正好是1 / 9,007,199,254,740,992。一般来说,四舍五入意味着您平均需要10个四十亿亿个样本才能找到0。当然,您可能会在前10次尝试中找到它,或者永远不会。
不可能对1进行采样,因为用括号将为值定义的间隔封闭,因此不包括1。
X ~ U(0,1)
,则P(X=x)
是几乎必然为0,对于x的所有值。(这是因为间隔中存在无限多个可能的值。)如果要查找正好为0或1,则应使用其他函数,例如random.choice