generators : random shootout

Mark McEahern marklists at mceahern.com
Tue Jan 15 17:27:29 EST 2002


GerritM wrote:
> can this instead be replaced by:
>
> for i in gen_random(100.0): pass

Short answer:  No.

Why not?

1.  Calling the generator returns an iterator.  You need to call the
iterator, not the generator:

	gr = gen_random(100.0)
	for i in gr:pass

2.  If you call it this way, the proposed solution will not StopIteration,
so you have an infinite loop.

3.  You can add a counter parameter to the generator:

  def gen_random(max, N):
    n = 0
    last = 42                         # initialize
    while n < N:                      # test the counter
      n = n + 1				  # increment the counter
      last = (last * IA + IC) % IM    # update prior value
      rand = max * last / IM          # generate the random number
      yield rand                      # yield it

However, now you won't be able to display the last value.

**

Below is the solution I ended up with, in case you'd like to tinker with it.
As the shootout site stated, the solution should generate 8.163294467 for N
= 1000.

Cheers,

// mark

#! /usr/bin/env python
# gen2.py
# based on: http://www.bagley.org/~doug/shootout/

from __future__ import generators

import sys

IM = 139968     # modulo
IA = 3877       # multiplier
IC = 29573      # increment

def gen_random(max):
    last = 42                           # initialize
    while 1:                            # this generator can be called
indefinitely
        last = (last * IA + IC) % IM    # update prior value
        rand = max * last / IM          # generate the random number
        yield rand                      # yield it

def main():
    try:
        N = int(sys.argv[1])
    except IndexError:
        N = 1000
    if N < 1:
        N = 1
    gr = gen_random(100.0)
    for i in xrange(1, N):
        gr.next()
    print "%.9f" % gr.next()

import time
timeIn = time.time()
main()
timeOut = time.time()

print "%f seconds." % (timeOut - timeIn)






More information about the Python-list mailing list