Problem with returning prime number in a simple calculation program
Steven D'Aprano
steve at REMOVE.THIS.cybersource.com.au
Sat Mar 3 19:32:48 EST 2007
On Sat, 03 Mar 2007 15:36:36 -0800, QHorizon wrote:
> Hello, I'm new to Python (I've learned everything up to iterators so
> far) and fairly new to Programming. This would be my first real
> program:
>
> #Coordinate Geometry (The whole program is not shown)
>
> import math
> import sys
>
> print "Welcome to the Coordinate Geometry Calculator!"
> print "Type 'terms' for a list of commands"
>
> def main():
[snip big boring series of if...elif... statements]
You're eventually going to run into a run time recursion error if you run
that for long enough. Can you see why?
A better way to do a command loop is something like this:
def bad_command():
# called when the user enters an unrecognized command
print "Unknown command, please try again"
class QuitException(Exception):
# used for exiting the loop
pass
def main():
# Make a "dispatch table" that maps the name of a command
# (as typed by the user) with a function to call.
dispatcher = {'slope': do_slope,
'primes': do_primes,
'quit': do_quit,
# ... and more here
}
try:
# loop forever (until we jump out of it)
while True:
cmd = get_command_from_user()
# you have to write get_command_from_user yourself
func = dispatcher.get(cmd, bad_command)
result = func()
print result
except QuitException:
print "Goodbye, come again soon!"
Now you just need to define your individual functions do_slope, do_primes,
etc. The only "special" one is do_quit.
def do_quit():
raise QuitException
Now let's look at the do_primes function. (You call it "prime".)
> def prime():
> num = input("Number ")
That's a good way to have malicious users do really, really really bad
things to your PC.
Safer is to do this:
num = int(raw_input("Number "))
> i = num - 1
> divcounter = 0
> while i > 1:
> if num % i != 0:
> divcounter += 1
> i -= 1
That's an inefficient algorithm, if it even works. I'm not sure that it
works, and I'm too lazy to find out :)
> if divcounter == num - 2:
> print num, "is a prime number"
> else:
> print num, "is not a prime number"
This will only work if divcounter happens to equal the original number
less two. If it equals something else, nothing will be printed.
Here's a simple algorithm to check if a number is prime.
# Warning: untested.
def do_primes():
num = int(raw_input("Number ")
if num <= 1:
return "%n is not prime" % num
if num == 2:
return "%n is prime" % num
elif num % 2 == 0:
# even numbers other than 2 aren't prime
return "%n is not prime" % num
for i in range(3, num, 2):
if num % i == 0:
return "%n is not prime" % num
return "%n is prime" % num
Now, this is deliberately not an efficient algorithm. There are things you
can do to make it more efficient, or you can re-write it completely.
The thing to remember is, don't PRINT the result, RETURN it. Your
do_primes() function should only calculate the result, and pass that
result up to the main loop for printing (or writing to a text file, or
emailing, or whatever).
Have fun!
--
Steven.
More information about the Python-list
mailing list