Trying to create a Random Number Generator that depending on the number outputs a statement. I keep getting the output of Over 50 no matter what. I can't seem to figure out why though.
from random import randrange
print randrange(100)
number = randrange
if number <= 49:
print"Under 50"
else:
print"Over 50"
Changing the following line corrected the issue.
number = randrange(100)
This statement doesn't do what you think:
number = randrange
It's setting number to the function, not to a result from calling the function. If you now did print number(100) you'd see what I mean. Python 2 allows you to compare arbitrary values to each other, even if they're not really comparable, so the <= doesn't fail but doesn't deliver a result that makes sense either. Python 3 would generate an error if you tried to do the same thing.
Related
I tried two different ways to get a coin flip result, seeding the RNG first in order to get reproducible results.
First, I tried using random.randint:
import random
random.seed(23412)
flip = random.randint(0,1)
if flip == 0:
print("Tails")
else:
print("Heads")
For this seed, I get a Heads result; the flip result is 1.
Then, I tried rounding the result of random.random:
import random
random.seed(23412)
flip = random.random()
print(flip) # for testing purposes
new_flip = round(flip)
if new_flip == 0:
print("Tails")
else:
print("Heads")
This time, I get a value for flip of 0.27484468113952387, which rounds to 0, i.e. a Tails result.
Why does the result differ? Shouldn't random.randint pull the same random value (since the seed was the same), and flip the coin the same way?
Seeding a random number generator ensures a reproducible stream of underlying raw data. Different random module methods will compute their results in different ways, using different amounts of data.
The exact computation is an implementation detail. In the implementation I use (although I suspect it is the same for many other versions), random.randint will use the next single bit of raw data from the stream - it does a bunch of math first to figure out how many possible answers there are in range, then rounds that up to the next power of two, then chooses the corresponding number of bits to get a value (0..2n-1), repeats that until it's in range, and finally does more math to scale that to the original range. (If you tried, for example, random.randint(0, 2), it would repeatedly grab two bits interpreted as an integer, until the result isn't 3 which is out of range.)
The implementation of random.random is hidden in the C code, but I assume that it grabs multiple bits of data (at least 53) in order to fill the mantissa of a machine double-precision floating-point value.
Once you set a seed, all random numbers that follow will be consistent. It does not mean that all random numbers will be the same (and not be random any more).
However, once you re-set the seed, the random number generation will start from the beginning. Therefore it's predictable what will happen, e.g. like this, where 200 random numbers are generated in a 100 loops and I can predict each outcome (via assertions)
import random
for i in range(100):
test_seed = 23412
random.seed(test_seed)
flip = round(random.random())
assert flip == 0 # predict "Tails"
if flip == 0:
print("Tails")
else:
print("Heads")
flip = random.randint(0,1)
assert flip == 1 # predict "Heads"
if flip == 0:
print("Tails")
else:
print("Heads")
I've been running some code for an hour or so using a rand.int function, where the code models a dice's roll, where the dice has ten faces, and you have to roll it six times in a row, and each time it has to roll the same number, and it is tracking how many tries it takes for this to happen.
success = 0
times = 0
count = 0
total = 0
for h in range(0,100):
for i in range(0,10):
times = 0
while success == 0:
numbers = [0,0,0,0,0,0,0,0,0,0]
for j in range(0,6):
x = int(random.randint(0,9))
numbers[x] = 1
count = numbers.count(1)
if count == 1:
success = 1
else:
times += 1
print(i)
total += times
success = 0
randtst = open("RandomTesting.txt", "a" )
randtst.write(str(total / 10)+"\n")
randtst.close()
And running this code, this has been going into a file, the contents of which is below
https://pastebin.com/7kRK1Z5f
And taking the average of these numbers using
newtotal = 0
totalamounts = 0
with open ('RandomTesting.txt', 'rt') as rndtxt:
for myline in rndtxt: ,
newtotal += float(myline)
totalamounts += 1
print(newtotal / totalamounts)
Which returns 742073.7449342106. This number is incorrect, (I think) as this is not near to 10^6. I tried getting rid of the contents and doing it again, but to no avail, the number is nowhere near 10^6. Can anyone see a problem with this?
Note: I am not asking for fixes to the code or anything, I am asking whether something has gone wrong to get the above number rather that 100,000
There are several issues working against you here. Bottom line up front:
your code doesn't do what you described as your intent;
you currently have no yardstick for measuring whether your results agree with the theoretical answer; and
your expectations regarding the correct answer are incorrect.
I felt that your code was overly complex for the task you were describing, so I wrote my own version from scratch. I factored out the basic experiment of rolling six 10-sided dice and checking to see if the outcomes were all equal by creating a list of length 6 comprised of 10-sided die rolls. Borrowing shamelessly from BoarGules' comment, I threw the results into a set—which only stores unique elements—and counted the size of the set. The dice are all the same value if and only if the size of the set is 1. I kept repeating this while the number of distinct elements was greater than 1, maintaining a tally of how many trials that required, and returned the number of trials once identical die rolls were obtained.
That basic experiment is then run for any desired number of replications, with the results placed in a numpy array. The resulting data was processed by numpy and scipy to yield the average number of trials and a 95% confidence interval for the mean. The confidence interval uses the estimated variability of the results to construct a lower and an upper bound for the mean. The bounds produced this way should contain the true mean for 95% of estimates generated in this way if the underlying assumptions are met, and address the second point in my BLUF.
Here's the code:
import random
import scipy.stats as st
import numpy as np
NUM_DIGITS = 6
SAMPLE_SIZE = 1000
def expt():
num_trials = 1
while(len(set([random.randrange(10) for _ in range(NUM_DIGITS)])) > 1):
num_trials += 1
return num_trials
data = np.array([expt() for _ in range(SAMPLE_SIZE)])
mu_hat = np.mean(data)
ci = st.t.interval(alpha=0.95, df=SAMPLE_SIZE-1, loc=mu_hat, scale=st.sem(data))
print(mu_hat, ci)
The probability of producing 6 identical results of a particular value from a 10-sided die is 10-6, but there are 10 possible particular values so the overall probability of producing all duplicates is 10*10-6, or 10-5. Consequently, the expected number of trials until you obtain a set of duplicates is 105. The code above took a little over 5 minutes to run on my computer, and produced 102493.559 (96461.16185897154, 108525.95614102845) as the output. Rounding to integers, this means that the average number of trials was 102493 and we're 95% confident that the true mean lies somewhere between 96461 and 108526. This particular range contains 105, i.e., it is consistent with the expected value. Rerunning the program will yield different numbers, but 95% of such runs should also contain the expected value, and the handful that don't should still be close.
Might I suggest if you're working with whole integers that you should be receiving a whole number back instead of a floating point(if I'm understanding what you're trying to do.).
##randtst.write(str(total / 10)+"\n") Original
##randtst.write(str(total // 10)+"\n")
Using a floor division instead of a division sign will round down the number to a whole number which is more idea for what you're trying to do.
If you ARE using floating point numbers, perhaps using the % instead. This will not only divide your number, but also ONLY returns the remainder.
% is Modulo in python
// is floor division in python
Those signs will keep your numbers stable and easier to work if your total returns a floating point integer.
If this isn't the case, you will have to account for every number behind the decimal to the right of it.
And if this IS the case, your result will never reach 10x^6 because the line for totalling your value is stuck in a loop.
I hope this helps you in anyway and if not, please let me know as I'm also learning python.
I am trying to write a program that generates a random number from a random number generated by a Perlin noise. If you ask why I am trying to add a little bit more randomness to a random number generator and see how that would work.
Anyways my problem is from the Perlin noise random number I always get 12 digit random numbers like: 124592051214, 431268750000, 420799999999, 613979257812...
the thing is I want this function to be used just like a normal python Random function. You give the borders(a,b) and you get a random number in those borders.
So, how can I turn a 12 digit number to match the given borders? Thanks in advance
ex:
num = 124592051214
perlinRand(50,100)
62
You can do something like
perlin_noise % (higher-lower) + lower
where "higher" is the higher limit of the random number you want, "lower" is the lower limit and perlin_noise is the number you generate
def perlinRand(lower, higher):
perlin_noise = get_perlin_noise_random_number()
return perlin_noise % (higher-lower) + lower
perlinRand(50, 100)
I'm trying to emulate a really simple version of the gamble game "Crash", where there's a number that increases every second and it's also the multiplier of your credits. So if you put in 50 credits and the multiplier goes to 3.30, you will get 50*3.30=165 credits. The number randomly crashes, and if you did not withdraw your money, you lose them.
from random import randrange, randint
crash_max_range = 50
crash_min_range = 0
multiplier_crash = list(range(crash_min_range, crash_max_range))
multiplier_crash = [float(i) for i in multiplier_crash]
print(*multiplier_crash, sep="\n")
The main thing that i'm struggling with is printing the float list which should look like
0
0.01
0.02
0.03
etc.. (every number on a new line)
I don't also know how to increase the chance that it will crash like 70% of the time at a low range because obviously the player can't always win.
Could you help me with that?
For a simulation you would normally use a loop that does one step at a time. I suggest using an infinite loop and a break statement on a random condition.
Inside this loop you will only need to print a single value in every print. You should use the str.format() method for any new code.
The code might then look like this:
import random
multiplier = 1.00
while True:
print('{:.2f}'.format(multiplier))
if random.random() < 0.1:
break
multiplier += 0.01
print('CRASH')
The above example is not perfect, because floating point errors accumulate when it is run for a long time. It might be better to use an integer and scale it for output.
Using itertools you can do it like this.
import itertools
import random
for i in itertools.count(100):
multiplier = float(i) / 100.0
print('{:.2f}'.format(multiplier))
if random.random() < 0.1:
break
print('CRASH')
This could be further simplified using generator expressions. However, the code might be less clear when you are just beginning pyhton.
import itertools
import random
for multiplier in (float(i) / 100.0 for i in itertools.count(100)):
print('{:.2f}'.format(multiplier))
if random.random() < 0.1:
break
print('CRASH')
I'm not clear on the crashing story, but if you're wanting the float list to be printed in increments of .01 up to like that, one thing you could do is to change these two lines like this:
multiplier_crash = list(range(crash_min_range, crash_max_range * 100))
multiplier_crash = [float(i) / 100 for i in multiplier_crash]
That will print the initial 0 as 0.0, though ... if you want numbers like 0 and 1 and so on to print without the trailing .0 as in your example, one way you could do that would be to replace the second line above like this:
multiplier_crash = ["{:,g}".format(float(i) / 100) for i in multiplier_crash]
so I am stuck on how to make my program assign a random number between two floats to a variable. This is my code:
dmg = self.lvl/2
I want the damage to be a random selection between + 3 or -3 of the caharcters level divided by two. How would I do this?
dmg = random.randint(self.lvl/2+3, self.lvl/2-3)
I tried this but it did not work.
You can use random.uniform(a,b).
random.uniform(1.5, 1.9)
Gives 1.8733202628557872
Hope this is what you want.