在文档中,据说有机会uniform(0,1)
生成值0
和1
.
我已经运行了uniform(0, 1)
10000 次,但它从未产生过零。即使在uniform(0, 0.001)
.
可以random.uniform(0,1)
生成0
or1
吗?
在文档中,据说有机会uniform(0,1)
生成值0
和1
.
我已经运行了uniform(0, 1)
10000 次,但它从未产生过零。即使在uniform(0, 0.001)
.
可以random.uniform(0,1)
生成0
or1
吗?
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
random()
1.0
返回 [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, 0.001)
了。只要继续限制界限以使其更快发生。
>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
5e-324
>>> random.uniform(0., 5e-324)
0.0
您可以尝试生成一个循环来计算所需的迭代次数,以便显示精确的 0(不要)。
此外,正如霍布斯所说,被uniformly
采样的值的数量是 9,007,199,254,740,992。这意味着看到 0 的概率正好是 1/9,007,199,254,740,992。一般而言,四舍五入意味着您平均需要10 万亿个样本才能找到 0。当然,您可能会在前 10 次尝试中找到它,或者永远不会找到它。
采样 1 是不可能的,因为为值定义的区间用括号封闭,因此不包括 1。