random.randint(1,10)可以返回11吗?

时间:2010-06-14 14:16:57

标签: python random bounds

在研究this question并阅读random.py中的源代码时,我开始怀疑randrangerandint是否真的表现为“广告宣传”。我非常倾向于这么认为,但是我读它的方式,randrange基本上实现为

start + int(random.random()*(stop-start))

(假设startstop的整数值),因此randrange(1, 10)应返回1到9之间的随机数。

randint(start, stop)正在调用randrange(start, stop+1),从而返回1到10之间的数字。

我现在的问题是:

如果random()曾要返回1.0,那么randint(1,10)会返回11,不是吗?

3 个答案:

答案 0 :(得分:27)

来自random.py和文档:

"""Get the next random number in the range [0.0, 1.0)."""

)表示间隔独占 1.0。也就是说,它永远不会返回1.0。

这是数学中的一般惯例,[]是包容性的,而()是排他性的,两种类型的括号可以混合为(a, b][a, b)。请查看wikipedia: Interval (mathematics)以获得正式解释。

答案 1 :(得分:12)

其他答案指出,random()的结果始终严格小于1.0;然而,这只是故事的一半。

如果您将randrange(n)计算为int(random() * n),那么 还需要知道任何满足x的Python浮点0.0 <= x < 1.0,以及任何正整数n0.0 <= x * n < n都是如此,因此int(x * n)严格小于n

这里有两件事可能出错:首先,当我们计算x * n时,n被隐式转换为浮点数。对于足够大的n,该转换可能会改变该值。但是如果你看一下Python源代码,你会发现它只使用int(random() * n)方法n小于2**53(这里和下面我假设平台使用IEEE 754双打),这是保证n到浮点数的转换不会丢失信息的范围(因为n可以完全表示为浮点数)。

可能出错的第二件事是乘法x * n的结果(现在作为浮点数的产物执行,记得)可能不会完全可以表示,因此会有一些舍入参与其中。如果x足够接近1.0,则可以想到舍入会将结果四舍五入到n本身。

要看到这种情况不会发生,我们只需要考虑x的最大可能值,即(几乎所有运行Python的计算机上)1 - 2**-53。因此,我们需要针对正整数(1 - 2**-53) * n < n显示n,因为random() * n <= (1 - 2**-53) * n始终是真的。

证明(草图)让k成为k的唯一整数2**(k-1) < n <= 2**k。然后,n的下一个向下浮动为n - 2**(k-53)。我们需要证明n*(1-2**53)(即产品的实际,未包含的价值)更接近n - 2**(k-53)而不是n,因此它将始终向下舍入。但是一个小算术表明从n*(1-2**-53)n的距离是2**-53 * n,而从n*(1-2**-53)n - 2**(k-53)的距离是(2**k - n) * 2**-53。但2**k - n < n(因为我们选择了k以便2**(k-1) < n),因此产品 更接近n - 2**(k-53),因此将< / em>向下舍入(假设,即平台正在做某种形式的舍入到最近)。

所以我们很安全。呼!


附录(2015-07-04):以上假设采用IEEE 754二进制64算法,采用圆形连接到均匀舍入模式。在许多机器上,这种假设是相当安全的。但是,在使用x87 FPU进行浮点运算的x86机器上(例如,32位Linux的各种风格),乘法中有double rounding的可能性,这使得{{1}成为可能在random() * n返回最大可能值的情况下,将向上舍入到n。可能发生这种情况的最小random()n。有关详情,请参阅http://bugs.python.org/issue24546上的讨论。

答案 2 :(得分:3)

来自Python文档:

  

几乎所有模块函数都依赖于函数random(),它在半开放范围[0.0,1.0]内均匀生成随机浮点数。

几乎每个PRNG的浮点数......