Python:为什么 `random.randint(a, b)` 返回包括 `b` 的范围?

63

对我来说,random.randint(a, b) 返回 [a, b] 范围内的整数,而不是像 range(...) 一样返回 [a, b-1] 的范围,这一直让我感到奇怪。

这种表面上的不一致性是否有任何原因呢?


9
好的,你可以使用 randrange - kennytm
也许我不像你那样精明,但我并不认为这是不一致的。我只是认为这提供了一种方法,让程序员在不需要使用运算符和魔数的情况下调用一个包容性随机数。更好的编程语言为用户提供了创造性的途径。 - Musixauce3000
1
@Musixauce3000 这是一种不一致性,因为rangerandint两种方法都接受相同的逻辑值(即一组数字范围),但该值以两种不同的,不一致的方式进行指定(即一个包括端点,另一个排除端点)。 - David Wolever
为什么你希望它变得不那么直观? - endolith
4个回答

97
我尝试通过查看一些旧的资源来深入了解这个问题。我怀疑在Python的长整数之前实现了randint:这意味着如果你想要一个包括INT_MAX的随机数,你需要调用random.randrange(0, INT_MAX + 1),这将导致溢出并产生(0, 0)(0, INT_MIN)参数。

然而,即使是在Python 1.5.2源代码中,我们也可以看到:Lib/whrandom.py

#
# Get a random integer in the range [a, b] including both end points.
# (Deprecated; use randrange below.)
#
def randint(self, a, b):
    return self.randrange(a, b+1)

whrandom.randint2.0, 2.1, 2.22.3版本中被继续弃用;但是random.randint2.1版本中被标记为弃用,尽管在2.2版本中不再标记为弃用。

此外,从2.1版本开始的random.pyrandom.randint的文档字符串中首次提到:

def randrange(self, start, stop=None, step=1, int=int, default=None):
    """Choose a random item from range(start, stop[, step]).

    This fixes the problem with randint() which includes the
    endpoint; in Python this is usually not what you want.
    Do not supply the 'int' and 'default' arguments.
    """

目前唯一可用的比这个版本更老的源代码是0.9.1源代码,据我所知,那时还没有实现randint

因此,我得出结论,randint包括端点的原因只有Guido自己知道;根据Python 2.1中的文档字符串,听起来这个原因可能是一个简单的错误。


15
感谢你做出努力进行研究,并提出一些有趣的观察。+1 - Mark Byers
1
也许randint规范来自另一种语言? - user97370

16

我猜测random.randint只是实现这个功能的第一次尝试。看起来Python开发人员也觉得这是一个问题,这就是为什么在v1.5.2中他们添加了另一种方法randrange,它具有更标准的参数:

random.randrange([start], stop[, step])

从范围(start,stop,step)中返回一个随机选择的元素。这相当于choice(range(start, stop, step)),但不实际构建范围对象。

您可以使用randrange代替randint以避免令人惊讶的结果。

另一方面,在许多情况下,如果问题的表述为“在1到6之间选择一个随机数”,那么使用randint(1, 6)可能比编写randrange(1, 7)randrange(min, max + 1)更自然。


10
这只是猜测,但是普通人使用“从a到b给我一个随机数”的时候通常是包括a和b的。在Python中实现这种方式有点说得过去,因为Python一般的哲学是成为一种更易读的语言。

3

我认为没有理由这样做。但至少已经有记录了。


2
+1:原因并不重要。即使没有记录,它仍然不重要。 - S.Lott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接