Seeding and reusing Python random seeds

2019-04-22 19:40发布

I'm using Python and Flask to display a randomized game board, and trying to allow people to return to the same game by using a seed.

However, whether I use a random seed, or specify a seed, I seem to get the same pseudorandom sequences.

I cut out the majority of my code (I do a lot of splitting and joining with numpy) but even the simple code below shows the bug: no matter what value of seed I give the form, the number displayed on submit is the same. Submitting the form without specifying the seed shows a different number, but despite showing different seed values on reloading, that other number is always the same as well.

Am I doing something wrong with seeding?

from flask import Flask, request, render_template
import numpy as np
import random

app = Flask(__name__)

@app.route( '/' )
def single_page():
   return render_template( 'page.html', title = 'empty form' )

@app.route( '/number', methods = [ 'POST', 'GET' ] )
def render_page( title = 'generated random number', error = [] ):
   error = []
   if request.method == 'POST':
      if request.form['seed'].isdigit():
         seed = int( request.form['seed'] )
         error.append( "seed set: " + str( seed ) + "." )
         np.random.seed( seed/100000 )
      else:
         seed = int( 100000 * random.random() )
         error.append( "seed not set, " + str( seed ) + " instead." )
         np.random.seed( seed/100000 )

      n = np.random.random() * 100;

      return render_template('page.html', title=title, error=error, n=n, seed=seed )

   else:
      return render_template( 'page.html', title = 'empty form' )

if __name__ == '__main__':
   app.debug = True
   app.run()

Here is the flask HTML template

<!doctype html>
<html>
<head><title>{{title}}</title>
</head>
<body>
{% if error != '' %}
{% for message in error %}
    <h2>{{message}}</h2>
{% endfor %}
{% endif %}

{% if n %}
    <h2>Random number is {{n}}</h2>

    <h6>seed = {{ seed }}</h6>
{% else %}
    <div id="form">
    <form id="the_form" method="POST" action="number">
    Seed: <input type="number" min="1" max="99999" id="seed" name="seed"><br>
    <button id="submit" type="submit">Submit</button>
    </form>
{% endif %}
</div>
</body>
</html>

I multiply and divide the seeds by 100,000 so as to give a more memorable value (say, 4231 instead of 4.231479094...). Is there is a better way to have usable integer seed values?

UPDATED: Yes, there is a better way to do integer seed values - not mess with dividing at all. For the time being this is what I'm doing:

import numpy as np
import random
.
.
.
      if request.form['seed'].isdigit():
         seed = int( request.form['seed'] )
         error.append( "seed set: " + str( seed ) + "." )
         random.seed( seed )
      else:
         seed = int( 100000 * np.random.random() )
         error.append( "seed not set, " + str( seed ) + " instead." )
         random.seed( seed )

      n = random.random() * 100;

      return render_template('page.html', title=title, error=error, n=n, seed=seed )

This works fine. np.random.seed() didn't seem to always get the same sequence, but random.seed() doesn't mind an integer, so I'm using the latter.

1条回答
手持菜刀,她持情操
2楼-- · 2019-04-22 20:03

Your seed is probably an integer and integer division in early Python won't give a float. Thus

7078 / 100000 = 0

This always gives a seed of zero if seed is < 100000. With this:

np.random.seed( seed )

The seed should change. Without an argument np.random.seed should try to take a (system-dependent) seed.

If you want to read up on the PIP that "fixes" this the division: see PEP 238. In Python 3 this 2/5=0.4 in Python 2.X 2/5=0. You can force floating point upcasting at the top of your code by including the line:

from __future__ import division

Why use np.random instead of Python's random?

From the documentation:

The Python stdlib module “random” also contains a Mersenne Twister pseudo-random number generator with a number of methods that are similar to the ones available in RandomState. RandomState, besides being NumPy-aware, has the advantage that it provides a much larger number of probability distributions to choose from.

查看更多
登录 后发表回答