summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-07-31 13:39:44 (GMT)
committerGuido van Rossum <guido@python.org>1998-07-31 13:39:44 (GMT)
commit187f154243eb43b2d81f9b253458a16880e1b0bb (patch)
treeadcd2fcabffd96c3d7942469c1a3ff8497b42b52
parent490ec9c8773fd117cb724522b94eaac8e03932ef (diff)
downloadcpython-187f154243eb43b2d81f9b253458a16880e1b0bb.zip
cpython-187f154243eb43b2d81f9b253458a16880e1b0bb.tar.gz
cpython-187f154243eb43b2d81f9b253458a16880e1b0bb.tar.bz2
Introducing randrange([start,] stop [,step]) -- same as
choice(range(start, stop, step)) but faster. This addresses the problem that randint() was accidentally defined as taking an inclusive range (how unpythonic). The code is longish because Tim Peters insisted that it reject non-integral arguments while I insisted that it be not much slower than randint(); the compromise satisfies both but is somewhat convoluted. Also changed randint() to be implemented through randrange(). This is a semantic change because old randint() didn't test its arguments for validity. (It also makes randrange() win any contest with randint() :-)
-rw-r--r--Lib/whrandom.py42
1 files changed, 41 insertions, 1 deletions
diff --git a/Lib/whrandom.py b/Lib/whrandom.py
index 7f33fd6..3bfd14f 100644
--- a/Lib/whrandom.py
+++ b/Lib/whrandom.py
@@ -86,14 +86,53 @@ class whrandom:
return a + (b-a) * self.random()
#
# Get a random integer in the range [a, b] including both end points.
+ # (Deprecated; use randrange below.)
#
def randint(self, a, b):
- return a + int(self.random() * (b+1-a))
+ return self.randrange(a, b+1)
#
# Choose a random element from a non-empty sequence.
#
def choice(self, seq):
return seq[int(self.random() * len(seq))]
+ #
+ # Choose a random item from range([start,] step[, stop]).
+ # This fixes the problem with randint() which includes the
+ # endpoint; in Python this is usually not what you want.
+ #
+ def randrange(self, start, stop=None, step=1,
+ # Do not supply the following arguments
+ int=int, default=None):
+ # 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:
+ return int(self.random() * istart)
+ raise ValueError, "empty range for randrange()"
+ istop = int(stop)
+ if istop != stop:
+ raise ValueError, "non-integer stop for randrange()"
+ if step == 1:
+ if istart < istop:
+ return istart + int(self.random() *
+ (istop - istart))
+ raise ValueError, "empty range for randrange()"
+ istep = int(step)
+ if istep != step:
+ raise ValueError, "non-integer step for randrange()"
+ if istep > 0:
+ n = (istop - istart + istep - 1) / istep
+ elif istep < 0:
+ n = (istop - istart + istep + 1) / istep
+ else:
+ raise ValueError, "zero step for randrange()"
+
+ if n <= 0:
+ raise ValueError, "empty range for randrange()"
+ return istart + istep*int(self.random() * n)
# Initialize from the current time
@@ -104,3 +143,4 @@ random = _inst.random
uniform = _inst.uniform
randint = _inst.randint
choice = _inst.choice
+randrange = _inst.randrange