Is this python code doing what I want it to do?
I have this code
import random
b = 20
x = random.randrange(0,b)
y = random.randrange(0,b)
ab = 0
xc = 0
while ab != 10:
if x != y:
x = random.randrange(0,b)
y = random.randrange(0,b)
xc = xc + 1
elif x == y:
print ab
print 'number of tries out of', b, ' : ', xc
ab = ab + 1
xc = 0
y = 999999
it's essentially a stats program. I want to see out of 10 tries how many times a random number needs to be generated in order to match. So far the numbers i have been getting after running this program i get these values, i ran the program 5 times so that would be a total of 50 tries.
9
26
6
1
5
109
5开发者_如何转开发
42
12
63
All of those low numbers has led me to wondering if my program is just extremely lucky or if something is wrong my code. Thanks!
Note: is there a way i can get XC to add up after each while loop and when the while loop is true for it to show the total?
I'd say that you were somewhat unlucky.
The average there is 27.8. But if you pick two numbers between 0 and 20, you'd expect them to match about 1/20 of the time, and hence you expect to wait about 20 times before you get a match.
Check it with a larger number of iterations:
#!/usr/bin/env python
import random
max_num = 20
x = random.randrange(0, max_num)
y = random.randrange(0, max_num)
tries = 0
i = 0
iterations = 1000
total_tries = 0
while i < iterations:
if x != y:
x = random.randrange(0, max_num)
y = random.randrange(0, max_num)
tries += 1
else:
print(i)
print('number of tries out of %s : %s ' % (max_num, tries))
total_tries += tries
i += 1
tries = 0
y = -1
print("Average tries: %s" % (total_tries / iterations))
If I run this, I get ~20 every time.
Note: This could be simplified to this:
#!/usr/bin/env python
import random
max_num = 20
iterations = 1000
total_tries = 0
for i in range(iterations):
print(i)
tries = 0
x = 0
y = -1
while x != y:
x = random.randrange(0, max_num)
y = random.randrange(0, max_num)
tries += 1
print('number of tries out of %s : %s ' % (max_num, tries))
total_tries += tries
i += 1
tries = 0
print("Average tries: %s" % (total_tries / iterations))
Your logic is very strange.
You don't want to use artificial sentinel values to break out of a loop. Just explicitly break out of it.
You fundamentally have two loops: one to iterate over trials, and one to see how many attempts are needed in a given trial. Don't hide that structure.
Don't cover all the cases with
if
/else if
. That's whatelse
is for.Within a loop, generate numbers before you test them, not after. That way it's clearer what you're doing, and you don't need an extra generation step before the loop. Similarly, re-initialize values within a loop at the top, rather than the bottom.
Use clear variable names. When there isn't a meaningful variable name, avoid creating a variable. You don't actually need to set two variables to
random.randrange(0, b)
to compare the results. OTOH, if you want to simplify the logic and avoid writing a seemingly weird comparison ofrandom.randrange(0, b)
to itself, then you can note (and should be able to prove, if you're interested enough in this kind of stuff to write a program) that you can arbitrarily select a target value and get the same results. Also, use variables to name your arbitrarily selected numeric constants.You can use
+=
in Python to update a variable.Use print formatting.
import random
range_size = 20
total = 0
iterations = 1000 # or however many
for trial in xrange(iterations):
attempts = 0
while random.randrange(0, range_size) != 0: attempts += 1
print "Trial #{0}: Took {1} tries to match one of {2} numbers.".format(
trial, attempts, range_size
)
total += attempts
print "Average trials: {0}".format(float(total) / iterations)
If you don't need the debugging information, we can make things even cleaner by using built-in functions to do the summation and looping logic for us:
from random import randrange
from itertools import *
range_size = 20
total = 0
iterations = 1000 # or however many
print "Average trials: {0}".format(sum(
sum(takewhile(lambda x: randrange(0, range_size) != 0, repeat(1)))
# I tested that way, but this is probably more logical
# even if it's more verbose:
# len(list(takewhile(
# lambda x: x != 0,
# imap(randrange, repeat(0), repeat(range_size))
# )))
# 'lambda x: x != 0' can also be spelled 'bool' in this context,
# but explicit is better than implicit...
for i in xrange(iterations)
) / float(iterations))
精彩评论