其他答案指出,结果random()总是严格小于1.0;然而,这只是故事的一半。
如果您计算randrange(n)为int(random() * n),您还需要知道对于任何x满足的 Python 浮点数0.0 <= x < 1.0和任何正整数n,确实0.0 <= x * n < n,所以int(x * n)严格小于n。
这里有两件事可能会出错:首先,当我们计算时x * n,n会隐式转换为浮点数。对于足够大的n,该转换可能会改变值。但是,如果您查看 Python 源代码,您会发现它只使用小于的int(random() * n)方法(这里和下面我假设平台使用 IEEE 754 双精度),这是转换为浮点数的范围保证不会丢失信息(因为可以精确地表示为浮点数)。n2**53nn
可能出错的第二件事是乘法的结果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**-532**k - n < nk2**(k-1) < nn - 2**(k-53)
所以我们是安全的。呸!
附录(2015-07-04):以上假设 IEEE 754 binary64 算术,具有round-ties-to-even舍入模式。在许多机器上,这种假设是相当安全的。但是,在使用 x87 FPU 进行浮点运算的 x86 机器上(例如,各种风格的 32 位 Linux),在乘法中可能会进行双舍入,这使得在这种情况下可以向上random() * n舍入where返回最大的可能值。可能发生这种情况的最小的情况是. 有关更多信息,请参阅http://bugs.python.org/issue24546上的讨论。nrandom()nn = 2049