[Python Standard Library]random-Pseudo-Random Number Generator

Python version: 1.4 and later
The random module provides a fast pseudo-random number generator based on Mersenne Twister algorithm. This generator was originally developed to generate input to Monte Carlo simulation. Mersenne Twister algorithm generates a number of near-uniform distributions with a large period for various types of applications.
Generating Random Numbers
The random() function returns the next random floating-point value from the generated sequence. All returned values fall within the range of 0 <= n < 1.0.
import random

for i in xrange(5):
    print '%04.3f' % random.random(),
print
Repeated running of the program generates different sequences of numbers.
uniform() is used to generate a number within a specified range of values.
import random

for i in xrange(5):
    print '%04.3f' % random.uniform(1, 100),
print
Input minimum and maximum, uniform() adjusts the return value of random() using formula min + (max - min) * random().
Designated seeds
Each call to random() generates a different value, and the number repeats after a very large period. This is useful for generating unique or variable values, but in some cases it may be necessary to provide the same data set for processing in different ways. One technique is to use a program to generate random values and save them so that they can be processed separately through a single step. However, this may not be practical for large amounts of data, so random contains a seed() function to initialize the pseudo-random number generator so that it can generate a desired set of values.
import random

random.seed(1)

for i in xrange(5):
    print '%04.3f' % random.random(),
print
The seed value controls the first value generated by the formula used to generate the pseudo-random number. Since the formula is deterministic, the whole sequence to be generated is set after changing the seed. seed() can be any hash object. The default is to use a platform-specific random source (if any). Otherwise, if there is no such random source, the current time will be used.
Preserved status
The internal state of the pseudo-random algorithm used in random() can be preserved and used to control the random number generated in subsequent rounds. Restoring a state before continuing to generate a random number reduces the possibility of obtaining duplicate values or sequence of values from previous inputs. The getstate() function returns some data that can then be used by setstate() to reinitialize the pseudo-random number generator.
import random
import os
import cPickle as pickle

if os.path.exists('state.dat'):
    # Restore the previously saved state
    print 'Found state.dat, initializing random module'
    with open('state.dat', 'rb') as f:
        state = pickle.load(f)
    random.setstate(state)
else:
    # Use a well-known start state
    print 'No state.dat, seeding'
    random.seed(1)

# Produce random values
for i in xrange(3):
    print '%04.3f' % random.random(),
print
# Save state for next time
with open('state.dat', 'wb') as f:
    pickle.dump(random.getstate(), f)

# Produce more random values
print '\nAfter saving state:'
for i in xrange(3):
    print '%04.3f' % random.random(),
print
The data returned by getstate() is an implementation detail, so this example uses pickle to save the data to a file, but it can be treated as a black box. If the file exists at the beginning of the program, load the original state and continue. Each runtime generates a number before and after the state is saved to show that the restored state causes the generator to generate the same value again.
Random integer
random() generates floating-point numbers. You can convert the results to integers, but it's more convenient to use randint() directly to generate integers.
import random

print '[1, 100]:',
for i in xrange(3):
    print random.randint(1, 100),

print '\n[-5, 5]:',
for i in xrange(3):
    print random.randint(-5, 5),
print
The parameters of random() are the ends of the closed interval of the value. These numbers can be positive or negative, but the first value is less than the second.
randrange() is a more general form of selecting values from intervals.
import random

for i in xrange(3):
    print random.randrange(0, 101, 5),
print
In addition to the start and stop values, randrange() supports a step parameter, so it is completely equivalent to selecting a random value from the range(start, stop, step). But randrange It's more efficient because it doesn't really construct intervals.
Select random elements
A common use of random number generators is to select elements from a sequence of enumerated values, even if they are not numbers. Random includes a choice() function that can be randomly selected in a sequence. The following example simulates tossing a coin 10,000 times to count how many times it is facing up and how many times it is facing down.
import random
import itertools

outcomes = { 'heads':0,
             'tails':0,
             }
sides = outcomes.keys()

for i in range(10000):
    outcomes[ random.choice(sides) ] += 1

print 'Heads:', outcomes['heads']
print 'Tails:', outcomes['tails']
Since only two results are allowed, there is no need to use numbers and then convert them. Here the words "heads" and "tails" are used for choice(). The results are stored in a dictionary in tabular form, using the result name as the key.
array
To simulate a poker game, you need to mix up a deck of cards and deal to the player. The same card cannot be used many times. The use of choice() may result in the same card being issued twice, so shuffle() can be used to shuffle the cards, and then delete the cards issued when each card is issued.
import random
import itertools

FACE_CARDS = ('J', 'Q', 'K', 'A')
SUITS = ('H', 'D', 'C', 'S')

def new_deck():
    return list(itertools.product(
            itertools.chain(xrange(2, 11), FACE_CARDS),
            SUITS,
            ))
def show_deck(deck):
    p_deck = deck[:]
    while p_deck:
        row = p_deck[:13]
        p_deck = p_deck[13:]
        for j in row:
            print '%2s%s' % j,
        print

# Make a new deck, with the cards in order
deck = new_deck()
print 'Initial deck:'
show_deck(deck)

# Shuffle the deck to randomize the order
random.shuffle(deck)
print '\nShuffled deck:'
show_deck(deck)

# Deal 4 hands of 5 cards each
hands = [ [], [], [], [] ]

for i in xrange(5):
    for h in hands:
        h.append(deck.pop())

# Show the hands
print '\nHands:'
for n, h in enumerate(hands):
    print '%d:' % (n + 1),
    for c in h:
        print '%2s%s' % c,
    print

# Show the remaining deck
print '\nRemining deck:'
show_deck(deck)
These poker cards are represented as tuples, consisting of face value and a letter indicating pattern. To create a hand that has been issued, add one card to each of the four lists at a time, and then delete it from the deck so that the cards will not be issued again.
sampling
Many simulations require random samples from a large number of input values. The sample() function generates samples with no duplicate values and does not modify the input sequence. The following example prints a random sample of words in the system dictionary.
import random

with open('/usr/share/dict/words', 'rt') as f:
    words = f.readlines()
words = [ w.rstrip() for w in words ]

for w in random.sample(words, 5):
    print w
The algorithm for generating result sets takes into account the size of the input and the sample requested to generate the results as efficiently as possible.
Multiple concurrent generators
In addition to module level functions, random also includes a Random class to manage the internal state of multiple random number generators. All the functions described previously can be obtained as Random instances, and each instance can be initialized and used independently without interfering with the values returned by other instances.
import random
import time

print 'Default initializion:\n'

r1 = random.Random()
r2 = random.Random()

for i in xrange(3):
    print '%04.3f  %04.3f' % (r1.random(), r2.random())

print '\nSame seed:\n'

seed = time.time()
r1 = random.Random(seed)
r2 = random.Random(seed)

for i in xrange(3):
    print '%04.3f %04.3f' % (r1.random(), r2.random())
If a good seed of built-in random values is set on the system, different instances will have a unique initial state. However, without a good platform random value generator, different instances tend to use the current time as the seed, thus generating the same value.
To ensure that the generator generates values from different parts of the random cycle, jumpahead() can be used to adjust the initial state of one generator.
import random
import time

r1 = random.Random()
r2 = random.Random()

# Force r2 to a different part of the random period than r1.
r2.setstate(r1.getstate())
r2.jumpahead(1024)

for i in xrange(3):
    print '%04.3f  %04.3f' % (r1.random(), r2.random())
The jumpahead() parameter should be a non-negative integer based on the number of values required by each generator. The generator's internal state is adjusted according to this input value, but not just incremental by a given number of steps.
SystemRandom
Some operating systems provide a random number generator to access more sources of information that can be introduced into the generator. Random provides this feature through the SystemRandom class, which is the same as Random's API, but uses os.urandom() to generate values, which forms the basis for all other algorithms.
import random
import time

print 'Default initializion:\n'

r1 = random.SystemRandom()
r2 = random.SystemRandom()

for i in xrange(3):
    print '%04.3f  %04.3f' % (r1.random(), r2.random())

print '\nSame seed:\n'

seed = time.time()
r1 = random.SystemRandom(seed)
r2 = random.SystemRandom(seed)

for i in xrange(3):
    print '%04.3f %04.3f' % (r1.random(), r2.random())
The sequence generated by SystemRandom is non-renewable because its randomness comes from the system, not from the software state (in fact, seed() and setstate() do not work at all).
Non-uniform distribution
The values generated by random() are evenly distributed, which is very useful for many purposes, but other distributions can model specific situations more accurately. The random module also contains functions to generate such distributed values. These distributions are listed here, but they are not intended to be detailed because they are often used only under specific conditions and require more complex examples to illustrate.
1. Normal Distribution
Normal distribution is often used for non-uniform continuous values, such as gradient, height, weight, etc. The curve generated by normal distribution has a unique shape, so it is nicknamed "bell curve". random contains two functions that generate normal distribution values, normalvariate() and a faster gauss(). (Normal distribution is also called Gauss distribution)
There is also a related function lognormvariate(), which generates pseudo-random values with logarithmic normal distribution. Lognormal distribution is applicable to the product of multiple non-interactive random variables.
Approximate distribution
Triangular distribution is used for approximate distribution of small samples. In the "curve" of triangular distribution, the lowest point is the known minimum and maximum value, and there is a high point at the mode value, which should be estimated according to the "closest" result (reflected by the mode parameters of trianglar().
3. Exponential distribution
expovariate() can generate an exponential distribution, which can be useful for simulating arrival or interval values for homogeneous Poisson processes, such as radiation decay or requests to Web servers.
Many observable phenomena are applicable to Pareto distribution or power law distribution, which is popular because of Chris Anderson's "long tail effect". paretovariate() functions are useful for simulating resource allocation (people's wealth, musicians'needs, blog concerns, etc.).
4. Angular distribution
Mises distribution or circular normal distribution (generated by vonmises variate () is used to calculate the probability of periodic values, such as angle, calendar date and time.
5. Size distribution
Beta distribution is generated by betavariate(), which is often used in Bayesian statistics and applications, such as task duration modeling.
Gamma variate () generates a gamma distribution that is used to model the size of things, such as waiting time, rainfall and calculation errors.
weibullvariate() calculates Weber distribution for fault analysis, industrial engineering and weather forecasting. It describes the size distribution of particles or other discrete objects.


Keywords: Python less angular

Added by iceblossom on Thu, 18 Jul 2019 00:59:28 +0300