2

Context

Say, we want to use the Box-Muller algorithm. Starting from a couple of random numbers U1 and U2, we can generate G1 and G2. Now, for any call, we just want to output either G1 or G2. In other languages, we could use static variables to be able to know if we need to generate a new couple. How can it be done in Python?

First thoughts

I know, much had been said about static variables in Python, I also must say I'm a bit confused as the answers are quite scattered. I found this thread and references therein. By that thread, the solution here would be to use a generator.

The devil's in the details

Now, the problem is, how do we initialize the generator and how do we retain, say G2, for the next yield?

Community
  • 1
  • 1
green diod
  • 1,399
  • 3
  • 14
  • 29
  • 2
    Why don't you present some code of what you did and have not been able to achieve? – pyfunc Dec 23 '11 at 17:02
  • Have you tried [`random.gauss(0, 1)`](http://docs.python.org/library/random.html#random.gauss)? – Cameron Dec 23 '11 at 17:04
  • You could use class variables to accomplish what you'd like. See http://stackoverflow.com/questions/68645/static-class-variables-in-python. – Codie CodeMonkey Dec 23 '11 at 17:06
  • S. Lott provided the perfect solution for you: just implement your algorithm in reallyCalc and there you go! Python has not "static" (= global state) variables. http://stackoverflow.com/a/460811/1107807 – Don Question Dec 23 '11 at 17:10
  • Python doesn't have static variables. What feature of Python are you referring to? –  Dec 23 '11 at 17:21
  • @DeepYellow Ok, could work but I prefer something simple as we just want a stream of outputs, which seems to be the whole idea of having generators. Don-Question What do you call reallyCalc ?? – green diod Dec 23 '11 at 17:41

1 Answers1

3

Writing generators is a very good practice!

import random 
import math
def BoxMullerFormula(a,b):
    c = math.sqrt(-2 * math.log(a)) * math.cos(2 * math.pi * b)
    d = math.sqrt(-2 * math.log(a)) * math.sin(2 * math.pi * b)
    return (c,d)
def BoxM(): 
     while 1:
        Rand01 = random.random()
        Rand02 = random.random()
        (a,b) = BoxMullerFormula(Rand01,Rand02)
        yield a 
        yield b 

BoxM01 = BoxM()         
for i in xrange(10):
    print BoxM01.next() 

You should consider also having a class BoxMuller with a get() method, a re_initialize() one, and so on.

jimifiki
  • 5,377
  • 2
  • 34
  • 60
  • Thanks! So maybe it's my understanding of generators and the `yield` statement that's not good enough.
    Is it correct to say that the `yield` statement suspends the function execution and somehow all local variables are practically static?
    In my attempt, I wanted a way to yield G1 or G2 depending on some test but it appears there's no need for it here.
    – green diod Dec 23 '11 at 17:26
  • To initialize: def BoxM(seed = None): if seed: random.seed(seed) and then: BoxM01 = BoxM() BoxM02 = BoxM(13) – jimifiki Dec 23 '11 at 17:33
  • green diod you are right. Moreover each instantiation has its own static variables – jimifiki Dec 23 '11 at 17:35
  • What is the point with the get, re_initialize methods, and so on? I mean I would only initialize the U stream .. Sorry, our posts just crossed. I was busy looking at the various links – green diod Dec 23 '11 at 17:47
  • For Box-Muller random number generators you can just use iterators, it's fine. In general you may want to be able to perform more operations on your object, for instance skip(n) generations. It could be a method that your "class BoxMuller(myRandClass)" inerith from the base-class "myRandClass" you wrote with tha aim of having a common interface for all your own random number generators. – jimifiki Dec 23 '11 at 17:55