random.uniform(0,1) 可以生成 0 或 1 吗?
Can random.uniform(0,1) ever generate 0 or 1?
在the documentation中据说uniform(0,1)
有机会生成值0
和1
。
我有 运行 uniform(0, 1)
10000 次,但它从未产生零。即使在 uniform(0, 0.001)
的情况下。
random.uniform(0,1)
能否生成 0
或 1
?
"Several times" 不够。 10,000 不够。 random.uniform
从 2^53 (9,007,199,254,740,992) 个不同的值中选择。您对其中 两个 感兴趣。因此,在获得恰好为 0 或 1 的值之前,您应该期望生成几个 quadrillion 个随机值。所以这是可能的,但很有可能您永远不会观察到它。
uniform(0, 1)
可以产生 0
,但它 永远不会 产生 1
.
documentation 告诉您端点 b
可以 包含在生成的值中:
The end-point value b
may or may not be included in the range depending on floating-point rounding in the equation a + (b-a) * random()
.
所以对于 uniform(0, 1)
,公式 0 + (1-0) * random()
,简化为 1 * random()
,必须能够准确地产生 1
。只有当 random.random()
正好是 1.0
时才会发生这种情况。但是,random()
永远不会 产生 1.0
.
引用random.random()
documentation:
Return the next random floating point number in the range [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
中随机选择的 53 个这样的分数的总和(1/9007199254740992).
但是,由于它可以产生非常接近 1.0
的值,加上浮点数相乘时出现的舍入误差,您 可以 产生 b
对于 a
和 b
的 一些 值。但是 0
和 1
不在这些值中。
请注意 random.random()
可以 产生 0.0,因此 a
始终包含在 random.uniform()
的可能值中(a + (b - a) * 0 == a
).因为 random.random()
可以产生 2 ** 53
个不同的值(这 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
和 sys.float_info.max - (2 ** 970)
之间只有 1 个二进制分数差异,因此 random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
有 50-50 的机会产生 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
当然可以。你已经在正确的轨道上尝试 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。
在the documentation中据说uniform(0,1)
有机会生成值0
和1
。
我有 运行 uniform(0, 1)
10000 次,但它从未产生零。即使在 uniform(0, 0.001)
的情况下。
random.uniform(0,1)
能否生成 0
或 1
?
"Several times" 不够。 10,000 不够。 random.uniform
从 2^53 (9,007,199,254,740,992) 个不同的值中选择。您对其中 两个 感兴趣。因此,在获得恰好为 0 或 1 的值之前,您应该期望生成几个 quadrillion 个随机值。所以这是可能的,但很有可能您永远不会观察到它。
uniform(0, 1)
可以产生 0
,但它 永远不会 产生 1
.
documentation 告诉您端点 b
可以 包含在生成的值中:
The end-point value
b
may or may not be included in the range depending on floating-point rounding in the equationa + (b-a) * random()
.
所以对于 uniform(0, 1)
,公式 0 + (1-0) * random()
,简化为 1 * random()
,必须能够准确地产生 1
。只有当 random.random()
正好是 1.0
时才会发生这种情况。但是,random()
永远不会 产生 1.0
.
引用random.random()
documentation:
Return the next random floating point number in the range [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
中随机选择的 53 个这样的分数的总和(1/9007199254740992).
但是,由于它可以产生非常接近 1.0
的值,加上浮点数相乘时出现的舍入误差,您 可以 产生 b
对于 a
和 b
的 一些 值。但是 0
和 1
不在这些值中。
请注意 random.random()
可以 产生 0.0,因此 a
始终包含在 random.uniform()
的可能值中(a + (b - a) * 0 == a
).因为 random.random()
可以产生 2 ** 53
个不同的值(这 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
和 sys.float_info.max - (2 ** 970)
之间只有 1 个二进制分数差异,因此 random.uniform(sys.float_info.max - (2 ** 970), sys.float_info.max)
有 50-50 的机会产生 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
当然可以。你已经在正确的轨道上尝试 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。