[Tutor] Please critique my Fraq.py

Dick Moores rdm at rcblue.com
Mon Jul 19 17:19:38 CEST 2004


Tutors,

This may seem like a silly script to write. But it's just an exercise I 
set for myself. And it does compute that amazingly close approximation to 
PI, 355/113:

============================
Maximum denominator: 200
For pi, 355/113 is closest fraction
     up to maximum denominator of 200
Error is 8.4913678767406e-006 percent
===========================

You'll notice that I've had to use this if statement twice in order to 
enable user to close the program:
if choice in ["x", "q"]:
          break

And also twice:
if maximumDenom in ["x", "q"]:
          break

And this:
if minimumError in ["x", "q"]:
          break

Is there a better way to do this?

How about my variable and constant names?

And all the while loops are "while True:". This OK?

Should the script be a lot more modular?

Thanks, tutors.

Dick Moores

=============================
# Frac.py

print """
     Enter a decimal number and Frac will calculate a fraction
     for use as an approximation to the number. You can choose to
     set a maximum denominator for the fraction, or to set a
     minimum error for the fraction to satisfy.

     Enter e or E for the mathematical constant 2.7182818284590451,
     and pi or PI for the mathematical constant 3.1415926535897931.

     You may exit the program at any prompt by entering x or q.
     """

import random, time

defaultMinimumError = 0.01
defaultMaximumDenom = 100

def exit():
     print "Thank you for using Frac. Frac will now close"
     time.sleep(1.1) # to provide the user with enough time to read the 
message

while True:
     print "If no decimal entered, a random decimal " \
     "between 0.1 and 1.0 will be chosen."
     # for exiting via ^C or ^D
     try:
         string = raw_input("Decimal: ")
     except (TypeError, EOFError):
          break
     if string in ["x", "q"]:
         break
     if string in ["pi", "PI"]: decimal = 3.1415926535897931
     elif string in   ["E", "e"]: decimal = 2.7182818284590451
     elif string == "":
         while True:
             decimal = random.random()
             # permit only 0.1 <= decimal < 1.0
             if decimal >= .1:
                 break
         string = str(decimal)
         print decimal, "was picked at random for you.\n"
     else:
         try:
             decimal = float(string)
         except:
             print "That's not a decimal number! Try again."
             continue

     while True:
         choice = raw_input("Minimum error (e) or maximum denominator (d)? ")
         if choice in ["x", "q"]:
             break
         elif not (choice in ["e", "d"]):
             print "Enter d or e"
             continue
         else:
             break
     if choice in ["x", "q"]:
             break
     if choice == "d":
         while True:
             print "If no maximum denominator entered, the default is 100"
             maximumDenom = raw_input("Maximum denominator: ")
             if maximumDenom in ["x", "q"]:
                 break
             elif maximumDenom == "":
                 maximumDenom = defaultMaximumDenom
                 print "Maximum denominator is %g by default" % maximumDenom
             else:
                 try:
                     maximumDenom = int(maximumDenom)
                 except:
                     print "That's not an integer! Try again."
                     continue
             break
         if maximumDenom in ["x", "q"]:
             break
         leastError = 1
         for denom in xrange(1, maximumDenom + 1):
             num = round(decimal * denom)
             error = abs((num / denom - decimal) / decimal)
             if error < leastError:
                 leastError = error
                 bestDenom = denom
                 bestNum = num
             if leastError == 0: # should I have this if statement?
                 break

         print "For %s, %d/%d is closest fraction" % (string, 
int(bestNum), bestDenom)
         print "    up to maximum denominator of %d" % maximumDenom
         print "Error is %.13e percent" % (leastError * 100)
         print "\n"

     elif choice == "e":
         while True:
             print "If no minimum error entered, the default is %g 
percent" % defaultMinimumError
             minimumError = raw_input("Minimum error in percent: ")
             if minimumError in ["x", "q"]:
                 break
             elif minimumError == "":
                 minimumError = defaultMinimumError
                 print "Minimum error is %g by default" % defaultMinimumError
             else:
                 try:
                     minimumError = float(minimumError)
                 except:
                     print "That's not a decimal number!"
                     continue
             break
         if minimumError in ["x", "q"]:
             break

         denom = 0
         while True:
             denom += 1
             num = round(decimal * denom)
             error = abs((num / denom - decimal) / decimal) * 100
             if error <= minimumError:
                 break
         print "%d/%d is fraction with smallest denominator with error <= 
%.13g percent" % (num, denom, minimumError)
         print "Actual error is %.13e percent" % error
         print "\n"
exit()
==========End of Frac.py===============





More information about the Tutor mailing list