可以将random.uniform(0,1)生成0或1吗?

Ven*_*ndi 9 python random uniform-distribution

文档中,据说uniform(0,1)可以生成值01

我已经运行了uniform(0, 1)10000次,但从未产生过零。即使在uniform(0, 0.001)

能否random.uniform(0,1)产生01

Mar*_*ers 13

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

引用random.random()文档

返回范围为[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为和生成某些值。但是和不在这些值之中。ab01

请注意,它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
Run Code Online (Sandbox Code Playgroud)

如果您按b = 0.0,则我们除以1023次,上述数值表示我们在1019次除法后就很幸运。到目前为止,我发现的最高值(使用循环运行上述函数max())为8.095e-320(1008除法),但可能会有更高的值。这都是机会游戏。:-)

如果a和之间没有很多离散的步骤b(例如,何时ab具有较高的指数,也似乎相去甚远),也会发生这种情况。浮点值仍然仅仅是近似值,它们可以编码的值的数量是有限的。例如,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
Run Code Online (Sandbox Code Playgroud)


hob*_*bbs 5

“几次”是不够的。10,000还不够。random.uniform从2 ^ 53(9,007,199,254,740,992)个不同的值中选择。您对其中两个感兴趣。这样,您应该期望在获得恰好为0或1的值之前先生成几个四次方随机值。所以有可能,但是很可能永远不会观察到它。

  • 对于“ uniform(0,1)”,不可能“ 1”作为结果。那是因为函数被简单地定义为`def Uniform(a,b):返回a +(b-a)* random()`和`random()`永远不会产生`1.0`。 (2认同)
  • @MartijnPieters我相信您是正确的,我支持您的回答。我对此表示怀疑,但是我不确定,这是我回答的重点之外,所以我顺其自然:) (2认同)