2013-10-28 62 views
2

我一直想知道python中的random.randrange()函数如何返回 的一个值,该值在整个范围内的均匀偏差不是2的幂(这很容易,因为N位是随机产生的)randrange()函数是如何工作的?

提前致谢!

+2

那么,它都是开源的,所以ReadTheCodeLuke(tm)。 –

+0

我建议你阅读这个https://docs.python.org/2/library/random.html#random.randrange – 2014-04-14 11:42:22

回答

3

你可以阅读源代码:

文件位置:

>>> import random 
>>> random.__file__ 
'C:\\Python27\\lib\\random.pyc' 

文件'C:\\Python27\\lib\\random.py'

def randrange(self, start, stop=None, step=1, int=int, default=None, 
       maxwidth=1L<<BPF): 
    """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', 'default', and 'maxwidth' arguments. 
    """ 

    # This code is a bit messy to make it fast for the 
    # common case while still doing adequate error checking. 
    istart = int(start) 
    if istart != start: 
     raise ValueError, "non-integer arg 1 for randrange()" 
    if stop is default: 
     if istart > 0: 
      if istart >= maxwidth: 
       return self._randbelow(istart) 
      return int(self.random() * istart) 
     raise ValueError, "empty range for randrange()" 

    # stop argument supplied. 
    istop = int(stop) 
    if istop != stop: 
     raise ValueError, "non-integer stop for randrange()" 
    width = istop - istart 
    if step == 1 and width > 0: 
     # Note that 
     #  int(istart + self.random()*width) 
     # instead would be incorrect. For example, consider istart 
     # = -2 and istop = 0. Then the guts would be in 
     # -2.0 to 0.0 exclusive on both ends (ignoring that random() 
     # might return 0.0), and because int() truncates toward 0, the 
     # final result would be -1 or 0 (instead of -2 or -1). 
     #  istart + int(self.random()*width) 
     # would also be incorrect, for a subtler reason: the RHS 
     # can return a long, and then randrange() would also return 
     # a long, but we're supposed to return an int (for backward 
     # compatibility). 

     if width >= maxwidth: 
      return int(istart + self._randbelow(width)) 
     return int(istart + int(self.random()*width)) 
    if step == 1: 
     raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width) 

    # Non-unit step argument supplied. 
    istep = int(step) 
    if istep != step: 
     raise ValueError, "non-integer step for randrange()" 
    if istep > 0: 
     n = (width + istep - 1) // istep 
    elif istep < 0: 
     n = (width + istep + 1) // istep 
    else: 
     raise ValueError, "zero step for randrange()" 

    if n <= 0: 
     raise ValueError, "empty range for randrange()" 

    if n >= maxwidth: 
     return istart + istep*self._randbelow(n) 
    return istart + istep*int(self.random() * n) 
+0

我想与文森特的答案一起去。他的回答是'甜蜜和简单'对不起:) –

3

快速查看源代码后,这是基本的原则:

def randrange(start, stop, step) 
    width = stop - start 
    n = (width + step - 1) // step 
    return start + step * int(random() * n)