2

I really need help as I am stuck at the begining of the code.

I am asked to create a function to investigate the exponential distribution on histogram. The function is x = −log(1−y)/λ. λ is a constant and I referred to that as lamdr in the code and simply gave it 10. I gave N (the number of random numbers) 10 and ran the code yet the results and the generated random numbers gave me totally different results; below you can find the code, I don't know what went wrong, hope you guys can help me!! (I use python 2)

import random
import math

N = raw_input('How many random numbers you request?: ')
N = int(N)
lamdr = raw_input('Enter a value:')
lamdr = int(lamdr)

def exprand(lamdr):
    y = []
    for i in range(N):
        y.append(random.uniform(0,1))
    return y
y = exprand(lamdr)
print 'Randomly generated numbers:', (y)

x = []
for w in y:
    x.append((math.log((1 - w) / lamdr)) * -1)
print 'Results:', x
6
  • different from what? you mean you run it twice and you get different results each time? Commented Oct 25, 2016 at 16:03
  • I got two lists for random numbers and the results, which should depends on the given equation, but it doesn't match, so for example I got totally x values for the randomly generated y values Commented Oct 25, 2016 at 16:05
  • Are you expecting lambdr to be the seed value for your random.uniform() calls? You would need to seed it with random.seed(lambdr) first if so. Then you would get the same sequence of numbers for a given lambdr value. Commented Oct 25, 2016 at 16:07
  • above I meant totally different x values by the way. Besides I don't know how to seed my lamdr value it says it is not defined, I mean it is just a constant that you determine for the equation Commented Oct 25, 2016 at 16:11
  • Without specifying a seed value, you're going to get a different sequence from random.uniform() each time you run the script. Therefore, I would expect that your x values would be different, since your y values are also different. Also, in the code as written above, you aren't actually doing anything with the lambdr value in the exprand() function. You're just passing it along. I'm not sure what you were intending to do with it in exprand(). Commented Oct 25, 2016 at 16:28

2 Answers 2

4

After viewing the code you provided, it looks like you have the pieces you need but you're not putting them together.

You were asked to write function exprand(lambdr) using the specified formula. Python already provides a function called random.expovariate(lambd) for generating exponentials, but what the heck, we can still make our own. Your formula requires a "random" value for y which has a uniform distribution between zero and one. The documentation for the random module tells us that random.random() will give us a uniform(0,1) distribution. So all we have to do is replace y in the formula with that function call, and we're in business:

def exprand(lambdr):
    return -math.log(1.0 - random.random()) / lambdr

An historical note: Mathematically, if y has a uniform(0,1) distribution, then so does 1-y. Implementations of the algorithm dating back to the 1950's would often leverage this fact to simplify the calculation to -math.log(random.random()) / lambdr. Mathematically this gives distributionally correct results since P{X = c} = 0 for any continuous random variable X and constant c, but computationally it will blow up in Python for the 1 in 264 occurrence where you get a zero from random.random(). One historical basis for doing this was that when computers were many orders of magnitude slower than now, ditching the one additional arithmetic operation was considered worth the minuscule risk. Another was that Prime Modulus Multiplicative PRNGs, which were popular at the time, never yield a zero. These days it's primarily of historical interest, and an interesting example of where math and computing sometimes diverge.

Back to the problem at hand. Now you just have to call that function N times and store the results somewhere. Likely candidates to do so are loops or list comprehensions. Here's an example of the latter:

abuncha_exponentials = [exprand(0.2) for _ in range(5)]

That will create a list of 5 exponentials with λ=0.2. Replace 0.2 and 5 with suitable values provided by the user, and you're in business. Print the list, make a histogram, use it as input to something else...

Replacing exporand with expovariate in the list comprehension should produce equivalent results using Python's built-in exponential generator. That's the beauty of functions as an abstraction, once somebody writes them you can just use them to your heart's content.

Note that because of the use of randomness, this will give different results every time you run it unless you "seed" the random generator to the same value each time.

Sign up to request clarification or add additional context in comments.

Comments

2

WHat @pjs wrote is true to a point. While statement mathematically, if y has a uniform(0,1) distribution, so does 1-y appears to be correct, proposal to replace code with -math.log(random.random()) / lambdr is just wrong. Why? Because Python random module provide U(0,1) in the range [0,1) (as mentioned here), thus making such replacement non-equivalent.

In more layman term, if your U(0,1) is actually generating numbers in the [0,1) range, then code

import random
def exprand(lambda):
    return -math.log(1.0 - random.random()) / lambda

is correct, but code

import random
def exprand(lambda):
    return -math.log(random.random()) / lambda

is wrong, it will sometimes generate NaN/exception, as log(0) will be called

1 Comment

A comment or edit seems like a more appropriate response than a down-vote.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.