## random number generator

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

### random number generator

I am not very experienced in using OOP. I used it here so that I would not have to keep passing the seed around the program.

I would be grateful if anyone can tell me if I have made any silly errors here. It seems to work as I expected it to.

Code: Select all

``````# oop_rng.py
# Using the linear convergence method of D. H. Lehmer.
# By default, this program uses the MINST settings.
# MINST:        n = 2^31,     g = 7^5
# Forth - LC53: n = 2^32 - 5, g = 2^32 - 333333333
# Cray  - RANF: n = 2^48,     g = 44485709377909

from time import *

def main():
rng = Rng()
print("*** Random Numbers ***")
print("*** D. H. Lehmer's method. ***")
print("Enter count, start, end (separated by commas).")
while 1:
user = input("> ")
try:
c,s,e = user.split(',')
except ValueError:
if user == 't':
rng.test()
continue
else:
return
for i in range(int(c)):
print(rng.rng(int(s),int(e)), end = " ")
print()

class Rng():
def __init__(self):
"""Set modulus (n), multiplier (g) and seed."""
self.n = self.power(2,31)
self.g = self.power(7,5)
self.seed = self.get_seed()

def get_seed(self):
"""Uses system time to set a random seed."""
x = int(time() * 1000) % 1000
return self.coprime(x+1000)

def coprime(self, x):
"""Finds a value coprime with self.n."""
while 1:
if self.gcd(x, self.n) == 1:
return x
else:
x += 1

def rng(self, s, e):
"""Updates seed to get next random number."""
self.seed = (self.g * self.seed) % self.n
return self.get_int(s,e)

def get_int(self, s, e):
"""Returns integer between s and e."""
return int((self.seed / self.n) * (e-s +1)) + s

def power(self, x, y):
""""Returns x^y, for integer values of y."""
z = 1
while y != 0:
if y % 2 == 0:
x *= x
y //= 2
else:
z *= x
y -= 1
return z

def test(self):
"""Runs a test on 1000 random numbers and prints results."""
print("Seed =", self.seed)
print("Frequencies of digits 0-9 in 1000 trials:")
freq = [0]*10
for i in range(1000):
freq[self.rng(0, 9)]+= 1

for i,j in enumerate(freq):
print(i, ":", j)

def gcd(self, a, b):
"""Euclid's Algorithm."""
while b > 0:
a, b = b, a % b
return a

if __name__ == "__main__":
main()
``````

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

### Re: random number generator

Cannot spot any obvious mistakes - pretty good example of OOP.

Of course could nitpick about power() and coprime() being more generic functions (not specific to the random generator class and in a bigger piece of software could be used elsewhere) and should be put in a more generic 'maths' class ...and in fact there is a power operator already in Python.
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

### Re: random number generator

Digital Larry
Posts: 75
Joined: Tue Jul 24, 2012 9:10 pm
Location: Silicon Valley, CA

### Re: random number generator

Many years ago I needed a pseudo random number generator for 16 bit values in an 8031 based system I designed. I just experimented with different values of x and y in the very simple relationship:

next = last * x + y ( of course limited to 16 bits)

I don't recall the magical values of x and y but I was able to get a sequence that took over 20,000 iterations to repeat.