def _check_date_fields(year, month, day): year = _index(year) month = _index(month) day = _index(day) if not MINYEAR <= year <= MAXYEAR: raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year) if not 1 <= month <= 12: raise ValueError('month must be in 1..12', month) dim = _days_in_month(year, month) if not 1 <= day <= dim: raise ValueError('day must be in 1..%d' % dim, day) return year, month, day
def _check_time_fields(hour, minute, second, microsecond, fold): hour = _index(hour) minute = _index(minute) second = _index(second) microsecond = _index(microsecond) if not 0 <= hour <= 23: raise ValueError('hour must be in 0..23', hour) if not 0 <= minute <= 59: raise ValueError('minute must be in 0..59', minute) if not 0 <= second <= 59: raise ValueError('second must be in 0..59', second) if not 0 <= microsecond <= 999999: raise ValueError('microsecond must be in 0..999999', microsecond) if fold not in (0, 1): raise ValueError('fold must be either 0 or 1', fold) return hour, minute, second, microsecond, fold
def randrange(self, start, stop=None, step=_ONE): """Choose a random item from range(stop) or range(start, stop[, step]). Roughly equivalent to ``choice(range(start, stop, step))`` but supports arbitrarily large ranges and is optimized for common cases. """ # This code is a bit messy to make it fast for the # common case while still doing adequate error checking. istart = _index(start) if stop is None: # We don't check for "step != 1" because it hasn't been # type checked and converted to an integer yet. if step is not _ONE: raise TypeError('Missing a non-None stop argument') if istart > 0: return self._randbelow(istart) raise ValueError("empty range for randrange()") # Stop argument supplied. istop = _index(stop) width = istop - istart istep = _index(step) # Fast path. if istep == 1: if width > 0: return istart + self._randbelow(width) raise ValueError(f"empty range in randrange({start}, {stop}, {step})") # Non-unit step argument supplied. 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(f"empty range in randrange({start}, {stop}, {step})") return istart + istep * self._randbelow(n)
def binomialvariate(self, n=1, p=0.5): """Binomial random variable. Gives the number of successes for *n* independent trials with the probability of success in each trial being *p*: sum(random() < p for i in range(n)) Returns an integer in the range: 0 <= X <= n """ # Error check inputs and handle edge cases if n < 0: raise ValueError("n must be non-negative") if p <= 0.0 or p >= 1.0: if p == 0.0: return 0 if p == 1.0: return n raise ValueError("p must be in the range 0.0 <= p <= 1.0") random = self.random # Fast path for a common case if n == 1: return _index(random() < p) # Exploit symmetry to establish: p <= 0.5 if p > 0.5: return n - self.binomialvariate(n, 1.0 - p) if n * p < 10.0: # BG: Geometric method by Devroye with running time of O(np). # https://dl.acm.org/doi/pdf/10.1145/42372.42381 x = y = 0 c = _log(1.0 - p) if not c: return x while True: y += _floor(_log(random()) / c) + 1 if y > n: return x x += 1 # BTRS: Transformed rejection with squeeze method by Wolfgang Hörmann # https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.47.8407&rep=rep1&type=pdf assert n * p >= 10.0 and p <= 0.5 setup_complete = False spq = _sqrt(n * p * (1.0 - p)) # Standard deviation of the distribution b = 1.15 + 2.53 * spq a = -0.0873 + 0.0248 * b + 0.01 * p c = n * p + 0.5 vr = 0.92 - 4.2 / b while True: u = random() v = random() u -= 0.5 us = 0.5 - _fabs(u) k = _floor((2.0 * a / us + b) * u + c) if k < 0 or k > n: continue # The early-out "squeeze" test substantially reduces # the number of acceptance condition evaluations. if us >= 0.07 and v <= vr: return k # Acceptance-rejection test. # Note, the original paper errorneously omits the call to log(v) # when comparing to the log of the rescaled binomial distribution. if not setup_complete: alpha = (2.83 + 5.1 / b) * spq lpq = _log(p / (1.0 - p)) m = _floor((n + 1) * p) # Mode of the distribution h = _lgamma(m + 1) + _lgamma(n - m + 1) setup_complete = True # Only needs to be done once v *= alpha / (a / (us * us) + b) if _log(v) <= h - _lgamma(k + 1) - _lgamma(n - k + 1) + (k - m) * lpq: return k
def randrange(self, start, stop=None, step=_ONE): """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. """ # This code is a bit messy to make it fast for the # common case while still doing adequate error checking. try: istart = _index(start) except TypeError: istart = int(start) if istart != start: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer arg 1 for randrange()") _warn( 'non-integer arguments to randrange() have been deprecated ' 'since Python 3.10 and will be removed in a subsequent ' 'version', DeprecationWarning, 2) if stop is None: # We don't check for "step != 1" because it hasn't been # type checked and converted to an integer yet. if step is not _ONE: raise TypeError('Missing a non-None stop argument') if istart > 0: return self._randbelow(istart) raise ValueError("empty range for randrange()") # stop argument supplied. try: istop = _index(stop) except TypeError: istop = int(stop) if istop != stop: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer stop for randrange()") _warn( 'non-integer arguments to randrange() have been deprecated ' 'since Python 3.10 and will be removed in a subsequent ' 'version', DeprecationWarning, 2) width = istop - istart try: istep = _index(step) except TypeError: istep = int(step) if istep != step: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer step for randrange()") _warn( 'non-integer arguments to randrange() have been deprecated ' 'since Python 3.10 and will be removed in a subsequent ' 'version', DeprecationWarning, 2) # Fast path. if istep == 1: if width > 0: return istart + self._randbelow(width) raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) # Non-unit step argument supplied. 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()") return istart + istep * self._randbelow(n)
def randrange(self, start, stop=None, step=1): """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. """ # This code is a bit messy to make it fast for the # common case while still doing adequate error checking. try: istart = _index(start) except TypeError: if int(start) == start: istart = int(start) _warn( 'Float arguments to randrange() have been deprecated\n' 'since Python 3.10 and will be removed in a subsequent ' 'version.', DeprecationWarning, 2) else: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer arg 1 for randrange()") if stop is None: if istart > 0: return self._randbelow(istart) raise ValueError("empty range for randrange()") # stop argument supplied. try: istop = _index(stop) except TypeError: if int(stop) == stop: istop = int(stop) _warn( 'Float arguments to randrange() have been deprecated\n' 'since Python 3.10 and will be removed in a subsequent ' 'version.', DeprecationWarning, 2) else: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer stop for randrange()") try: istep = _index(step) except TypeError: if int(step) == step: istep = int(step) _warn( 'Float arguments to randrange() have been deprecated\n' 'since Python 3.10 and will be removed in a subsequent ' 'version.', DeprecationWarning, 2) else: _warn('randrange() will raise TypeError in the future', DeprecationWarning, 2) raise ValueError("non-integer step for randrange()") width = istop - istart if istep == 1 and width > 0: return istart + self._randbelow(width) if istep == 1: raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) # Non-unit step argument supplied. 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()") return istart + istep * self._randbelow(n)