]> granicus.if.org Git - python/commitdiff
Introducing randrange([start,] stop [,step]) -- same as
authorGuido van Rossum <guido@python.org>
Fri, 31 Jul 1998 13:39:44 +0000 (13:39 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 31 Jul 1998 13:39:44 +0000 (13:39 +0000)
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()
:-)

Lib/whrandom.py

index 7f33fd60799d4dca632a491a610cc2f0afe4c4bf..3bfd14f820c5aafed3afa1041cf5d48db431f37f 100644 (file)
@@ -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