This small script generates a random float beween 0 and 1 and then if its less than "0.000111111111111" it will print the message "found it"
import random
value = 0.4 / 3600
print value
while True:
rand = random.random()
print "RAND IS: " + str(rand) + "----- VAL IS " + str(value)
if rand < value:
print "found it"
So seemingly the script runs and it never actually "finds it", however when I comment out the print statement before the if statement the command line is FILLED with "found it" even though the rand value isn't less than value. What the hell?
Your while loop is designed to run forever as True is always True. You never break out of that infinite loop. Even if it finds the value, it just prints it because the condition you give to the while loop is still True. Since you cannot change the condition, you need to add a break statement:
while True:
rand = random.random()
print "RAND IS: " + str(rand) + "----- VAL IS " + str(value)
if rand < value:
print "found it"
break
Your program does find numbers that are both smaller and larger than 'value', whether or not it prints all of them out. It's just that the output, both ways, is confusing you. This is because: (a) your computer is faster than you can probably imagine, as long as it doesn't have to print anything; (b) but when it does have to print something it slows down to the point where you can actually see the printouts go by; (c) the number of iterations in between successful "findings" is bigger than you may have expected.
To demonstrate all of the above, I wrote this script:
#! /usr/bin/python
import time
import random
import csv
import sys
def how_long_until(v):
n = 0
start = time.clock()
rng = random.random
while True:
n += 1
if rng() < v: break
stop = time.clock()
return n, stop - start
wr = csv.writer(sys.stdout, quoting=csv.QUOTE_MINIMAL)
wr.writerow(("loops", "cpu.time"))
value = 0.4 / 3600
for _ in range(10000):
wr.writerow(how_long_until(value))
This generates random numbers until it finds one less than your "value", and then it writes out the number of loop iterations and the elapsed CPU time to find it. It does this TEN THOUSAND TIMES. On my computer, which is old but not that old, this program took six seconds to run.
And then I plotted histograms of both. First, let's look at the number of loops:
You can see that, although it often takes only a few thousand iterations to find a random number smaller than 0.4/3600, it can take as many as 80,000 iterations! This is why it might have seemed to you that "found it" was never being printed.
Now let's look at elapsed time:
It looks very similar to the histogram of the number of loops, but notice the X-axis scale. That's time in milliseconds. Even when it takes 80,000 iterations to find the next number smaller than 0.4/3600, it only takes the computer four milliseconds to accomplish that feat! This is why it seemed to you that "found it" was continuously getting printed when you commented out the per-iteration printout.
Related
I'm working on a casino program that gets a bet ($1-$50) from the user, then pulls a slot machine to display a three-string combination of "7", "cherries", "bar", or "(space)". Certain combinations will trigger a bet multiplier, and the user will win back this amount. The run should look like this: ask user for bet, show user the pull and their winnings, then ask user for a new bet, display a new pull, and so on.
Right now, I have everything down except for a couple problems - I cannot make it so that the program generates a new random combination for each pull. Secondly, the main loop continues forever, printing the user's pull and winnings forever. Below is the method that generates either "7", "cherries", etc.
def rand_string(self):
random.seed(0)
# produces a number between 0 and 999
test_num = random.randrange(1000)
# precompute cutoffs
bar_cutoff = 10 * TripleString.BAR_PCT
cherries_cutoff = bar_cutoff + 10 * TripleString.CHERRIES_PCT
space_cutoff = cherries_cutoff + 10 * TripleString.SPACE_PCT
# bar = 38%, cherries = 40%, space = 7%, seven = 15%
if test_num < bar_cutoff:
return TripleString.BAR
elif test_num < cherries_cutoff:
return TripleString.CHERRIES
elif test_num < space_cutoff:
return TripleString.SPACE
else:
return TripleString.SEVEN
And here is the loop in main:
while(True):
if bet == 0: #a bet of $0 ends the program
print("Please come again!")
break
else:
print("whirrr...and your pull is " +\
object.pull())
object.display(None)
I thought I could solve this by somehow adding 1 to random.seed() for each loop (we begin with random.seed(0), but for each new pull 1 is added so that random.seed(1) and so on), but I don't know how to go about doing this and I'm not even sure if it's doable. If someone could point out my mistakes here, that'd be great. (sorry if this makes no sense, I'm very new to Python).
You should only call random.seed(0) once in the program. By seeding every time you are reseting the pseudo random number generator and forcing it to produce the same number.
random.seed(0)
while(True):
if bet == 0: #a bet of $0 ends the program
...
You can read more about random seeding here.
`So I am just making something to test if I can make certain outputs based on inputs
Each time I try to enter an answer, nothing happens here
I used if elif statements with the in range() in them.
Nothing shows up when I type the answer
from random import randint
from termcolor import colored
repeat = True
from termcolor import colored
import time
import sys
import multiprocessing
print colored("Hello, this is a program to help you practice algebraic
expressions.","magenta")
print("")
time.sleep(4)
print colored("Alright let's start with something very basic...\nWhat is x
if
2x
= 32?","magenta")
prob = int(raw_input())
if int(prob) in range (16, 16):
print colored("Well done, you got the warmup correct","yellow")
elif int(prob) in range(1, 15):
print colored("Incorrect answer try again","red")
This line if int(prob) in range(16,16): is problem. Function range(x,y) generates list equals to [x,y), which means starting with x and including x, ending with y excluding y, so by that, you are asking if your number is in empty array.
Example:
list_of_numbers = range(12,16) gives us list with elements list_of_numbers = [12,13,14,15]
I have written this code removing all the functions that you haven't used and the coloured text which seemed to always error. range is generally used in "for" loops but in conditionals you need to use == if it is equal to > for greater than < less than != not equal to e.t.c.
import time
print ("Hello, this is a program to help you practice algebraic
expressions.")
print("")
time.sleep(4)
prob =int (input("Alright let's start with something very basic What is
x if 2x = 32? "))
if prob ==16:
print("Well done, you got the warmup correct")
else:
print("Incorrect answer try again")
`
My code is a PYTHON program that identifies if a number is prime or not. When I entered 45 however, it said that 45 was a prime, even though 45 isn't a prime number. Also, every time I run the program, it prints 'Sorry, the number you have entered is not prime.' or 'The number is indeed prime!' multiple times, instead of once. How do I make it print the output statements once and how can fix the program so that it says 45 IS NOT a prime number.
n = eval(input("Enter a number to find if that number is prime: "))
a = 2
while n > a:
if ((n % a) == 0) & (a != n):
print('Sorry, the number you have entered is not prime.')
break
else:
print('The number you have entered is indeed prime!')
Because you are printing it every time. If you want to break after finding/not finding the prime number, indent one more level for the break.
Also, this does not calculate prime numbers. It calculates if its even number.
Follow the solution here
Your code has some issues. To start with, you're never updating a, so you only ever check if the number n is even.
Once you fix that, you have two indentation problems. The first is that the break line needs to be inside the body of the if statement. Indent it more so that it's inside the if block.
The second indentation issue is more subtle. If you leave the else where it is, it will print out that the number is prime every time you test a potential factor that doesn't divide the number. That's both unhelpful (since it prints a lot) and wrong (since it says the number is prime even if it will later find a factor and say it's not prime). You can fix this by unindenting the else line so that it is lined up with the while statement. Using an else after a loop is an obscure bit of Python syntax. The body of the else only runs if the condition of the loop fails. It gets skipped if the loop exits due to a break statement.
Here's all of those necessary fixes together:
while n > a:
if ((n % a) == 0) & (a != n):
print('Sorry, the number you have entered is not prime.')
break # indent this line more!
a += 1 # increment a, so you don't keep checking 2 over and over
else: # unindent this line (and the next line too)
print('The number you have entered is indeed prime!')
There are some other things that could be improved in your code, though they aren't causing it to run incorrectly. I'd recommend using int instead of eval to parse your number, and I'd use the logical-and operator and instead of the bitwise-and operator & in the if statement (though actually you don't need either, since the a != n check is redundant, as the loop would have already ended if it was true).
So this code is meant to return the final error and the final logarithm of a number inputted by a user. Now my issue is that it doesn't run the loop, it just keeps going over the same number and it never ends. I am not sure if I have my print statements in the wrong area, or if I am doing the loop wrong but I want the loop to end when the error is less then 1x10^-9. It's possible my iterations are set up wrong too, not really sure what I messed up on here.
import math
import sys
#Computing natural log of x
#x value is input here
x = float(input("Please input a positive number: "))
#If x is not positive then program will not work, so it will exit
if x<=0:
print("Your number is not positive. System Shutdown.")
sys.exit()
#Retrieving ln(x) using the math command
lnx0 = math.log(x)
#Formula for approximate ln
xfrac = (x - 1)/(x + 1)
lnx = 0 #Initializing the approximating
i=0
#This is the code to make it go until it hits the error we want
while True:
ex = 2*i - 1
lnx += 2.0* (xfrac**ex / ex)
#Counter adding 1 to it
i+=1
#This is the error
err = math.fabs(lnx0 - lnx)
if err<0.0000000001:
break
#Priting approximate ln at end of loop
print ("ln(x) at " ,x,"is: " ,lnx)
#Final Error
print ("Final error is:" ,err)
#Number of itterations
#Printing accurate version of ln(x) just to see what it should be
print ("Your accurate value of ln(x) is: " ,lnx0)
I'm assuming you're using the fourth formula on this page to approximate the log function. If so, your i is starting at the wrong value; you've initialized it to 0 here, but it needs to start at 1.
Also, if you only want output after the answer has been found, rather than once per iteration, your print functions should be de-indented so they are outside the loop. Try:
import math
import sys
#Computing natural log of x
#x value is input here
x = float(input("Please input a positive number: "))
#If x is not positive then program will not work, so it will exit
if x<=0:
print("Your number is not positive. System Shutdown.")
sys.exit()
#Retrieving ln(x) using the math command
lnx0 = math.log(x)
#Formula for approximate ln
xfrac = (x - 1)/(x + 1)
lnx = 0 #Initializing the approximating
i=1
#This is the code to make it go until it hits the error we want
while True:
ex = 2*i - 1
lnx += 2.0* (xfrac**ex / ex)
#Counter adding 1 to it
i+=1
#This is the error
err = math.fabs(lnx0 - lnx)
if err<0.0000000001:
break
#Priting approximate ln at end of loop
print ("ln(x) at " ,x,"is: " ,lnx)
#Final Error
print ("Final error is:" ,err)
#Number of itterations
#Printing accurate version of ln(x) just to see what it should be
print ("Your accurate value of ln(x) is: " ,lnx0)
Result:
Please input a positive number: 5
ln(x) at 5.0 is: 1.6094379123624052
Final error is: 7.169509430582366e-11
Your accurate value of ln(x) is: 1.6094379124341003
Thanks to DSM for identifying the formula and possible fix
There are several problems with this. The first is that your computations are incorrect. I tried entering 'e' to 9 places. Your estimate, lnx, quickly degenerates to -3.3279+ and sticks there. This dooms you to an infinite loop, because the estimate will never get near the true value.
Others have already pointed out that you haven't traced your computations with print statements. I'll add another hint from my days in numerical analysis: use a restricted "for" loop until you've debugged the computations. Then trade it in for a "while err > tolerance" loop.
To address your most recent comment, you're not getting the same numbers. The first few terms are significant, but the infinite sequence quickly drops close to 0, so the additions don't show up after about 15-20 iterations.
Also print out ex and lnx values within the loop. Especially check the first one, where your exponent is -1; I believe that you've started the loop in the wrong place.
Finally, you might find this loop form a little easier to read. Get rid of your if...break statement and use this instead:
i = 1
err = 1
tolerance = 1e-10
# This is the code to make it go until it hits the error we want
while err >= tolerance:
Newbie to python and hit a snag in my latest program. Simply put, I'm trying to code up a decrement loop for a user input variable if possible. Essentially I have a global constant set to value e.g. 13, each time the program loops it prompts the user to input a value then that user value is shaved off 13 until it reaches 0. Problem is that it does shave it off but when it reiterates it resets the value to 13 and only removes the current iterate value entered. So if you enter 2 each iteration it just takes it down to 11... But I'm aiming for a result using 2 as an example again, 11, 8, 5, etc etc or using 3 as an example 10, 7, 4.... Any help guys will be much appreciated, cheers :)
a = 13
def main():
runLoop()
def runLoop():
while other_input_var > 0: # guys this is my main score accumulator
# variable and works fine just the one below
b=int(input('Please enter a number to remove from 13: '))
if b != 0:
shave(a, b)
def shave(a, b):
a -= b
print 'score is %d ' % a
if a == 0:
print "Win"
main()
In my humble opinion with such a small snippet the addtional functions end up over complicating things. However good to see you are getting the concept. I have not tested this but this should do the same thing you are looking for. Notice line 5 I insure that the number entered does not exceed the current value of a. This should help if they/you accidentally type something higher. Next step would be to put error handling if you haven't tried that yet see Python Error Handling . hope this helps!
def main():
a = 13
while a:
b = int(input("Please enter a number to remove from " + str(a) + " : "))
if b > 0 and b <= a:
a -= b
print "Score is ", str(a)
print "Win"
main()
Not an answer to your question, but rather a demonstration of string formatting. This is the old style, using the % "string interpolation operator".
a = 100
while a:
shave = int(raw_input("Input a number to subtract from %i:" % a))
if ( shave > 0 ) and ( shave <= a ):
a -= shave
else:
print ("Number needs to be positive and less than %i." % a)
A session with this program:
Input a number to subtract from 100:50
Input a number to subtract from 50:100
Number needs to be positive and less than 50.
Input a number to subtract from 50:30
Input a number to subtract from 20:20
The %i in the original string is a placeholder for an integer (i for integer) which is filled in later by the % operator on the string.
There's also %f for floating-point numbers, %s for strings, and so on. You can do nifty things like specify how many decimal points numbers should print with - %.3f for three decimal places - and so on.
Another example:
>>> "My name is %s and I'm %.2f metres tall." % ('Li-aung',1.83211)
"My name is Li-aung and I'm 1.83 metres tall."
This is a lot easier to read than:
"My name is " + name + " and I'm " + str(round(age,2)) + " metres tall"
Read up more about string formatting the old way or the new way.