python random.randint vs random.choice:使用相同值的不同结果

N. *_*can 7 python random

我要求我的学生编写一个 python 程序,其中将一对 6 面骰子掷 100 次的结果存储在一个列表中,然后绘制在直方图中。

我一直将 视为random.choice(1,2,3,4,5,6)劣等random.randint(1,6),直到我注意到使用更好的学生的直方图random.choice反映了预期结果。例如,在几乎所有使用 的学生的直方图中,12 (6+6) 的掷骰出现率异常高random.randint(1,6)。有人知道发生了什么事吗?

use*_*203 6

从文档中

几乎所有模块函数都依赖于基本函数 random(),它均匀地生成半开范围 [0.0, 1.0) 内的随机浮点数。Python 使用 Mersenne Twister 作为核心生成器。它产生 53 位精度浮点数,周期为 2**19937-1。C 中的底层实现既快速又线程安全。Mersenne Twister 是目前经过最广泛测试的随机数生成器之一。然而,由于它是完全确定性的,因此并不适合所有目的,并且完全不适合加密目的。

所以结果不应该有任何真正的差异。然而,我不同意这random.choice()不如randint(),事实上,随机选择实际上生成随机数的速度更快。当你查看源代码时:

def randint(self, a, b):
    return self.randrange(a, b+1)

def randrange(self, start, stop=None, step=1, _int=int, _maxwidth=1L<<BPF):
    istart = _int(start)
    if istart != start:
        # not executed
    if stop is None:
        # not executed

    istop = _int(stop)
    if istop != stop:
        # not executed
    width = istop - istart
    if step == 1 and width > 0:
        if width >= _maxwidth:
            # not executed
        return _int(istart + _int(self.random()*width))
Run Code Online (Sandbox Code Playgroud)

对于choice()

def choice(self, seq):
    return seq[int(self.random() * len(seq))]
Run Code Online (Sandbox Code Playgroud)

您可以看到randint()使用时会产生额外的开销randrange()

编辑 正如 @abarnert 在评论中指出的那样,这里实际上几乎没有性能差异,并且randint(1,6)是表示掷骰子的清晰直观的方式

我运行了 10000 卷,没有看到任何倾斜,因此您的输入样本可能太小:

在此输入图像描述

这是一个骰子掷两次的分布,它也是非常均匀的:

在此输入图像描述

我从这两个有用的答案中借用了其中的一些内容:选择的性能与 randint Is Pythons random.randint 统计上随机吗?,这对进一步阅读很有帮助。