[Tutor] Please take another look at my frac.py

Dick Moores rdm at rcblue.com
Mon Aug 2 03:04:02 CEST 2004


Danny Yoo will be disappointed, I'm sure. His kind post of Fri, 23 Jul 
2004 15:26:36 -0700 (PDT) tried to show me how to shorten the program by 
consolidating the functions that get user input, but I was unable to 
implement his suggestions. But I have made the program a lot more modular.

If there's some more work needed, please tell me.

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 can exit the program at any prompt by entering 0 (zero).
     """

import random, time

def exit():
     print "Thank you for using Frac. Frac will now close."
     time.sleep(1.1)

def getDecimalFromUser():
     while True:
         print "If nothing entered, a random decimal " \
         "between 0.1 and 1.0 will be chosen."
         string = raw_input("Decimal: ")
         if string in ["pi", "PI"]: decimal = 3.1415926535897931
         elif string in ["E", "e"]: decimal = 2.7182818284590451
         elif string == "":
             decimal = getRandomDecimal()
             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
         break
     return decimal

def getRandomDecimal():
     decimal = random.uniform(0.1, 1.0)
     return decimal

def getChoiceFromUser():
     while True:
         choice = raw_input("Minimum error (e) or maximum denominator (d)? ")
         if not (choice in ['d', 'D', 'e', 'E', '0']):
             print "Enter d or e"
             continue
         break
     return choice

def getMaxDenomFromUser():
     while True:
         print "If no maximum denominator entered, the default is 100"
         maxDenom = raw_input("Maximum denominator: ")
         if maxDenom == "":
             maxDenom = 100
             print "Maximum denominator is %g by default" % maxDenom
         else:
             try:
                 maxDenom = int(maxDenom)
             except:
                 print "That's not an integer! Try again."
                 continue
         break
     return maxDenom

def getMinimumErrorFromUser():
     while True:
         print "If no minimum error entered, the default is %g percent" % .01
         minimumError = raw_input("Minimum error in percent: ")
         if minimumError == "":
             minimumError = .01
             print "Minimum error is %g by default" % .01
         else:
             try:
                 minimumError = float(minimumError)
             except:
                 print "That's not a decimal number!"
                 continue
         break
     return minimumError

def bestFracForMaxDenom(decimal, maxDenom):
     leastError = 1
     for denom in xrange(1, maxDenom + 1):
         num = round(decimal * denom)
         error = abs((num / denom - decimal) / decimal)
         if error < leastError:
             leastError = error
             bestDenom = denom
             bestNum = num
             # leastError is a float; should I have this if statement?
             if leastError == 0:
                 break
     return int(bestNum), bestDenom, leastError

def bestFracForMinimumError(decimal, minimumError):
     denom = 0
     while True:
         denom += 1
         num = round(decimal * denom)
         error = abs((num / denom - decimal) / decimal) * 100
         if error <= minimumError:
             break
     return int(num), denom, error

while True:
     decimal = getDecimalFromUser()
     if decimal == 0:
         break
     choice = getChoiceFromUser()
     if choice == "0":
         break
     if choice == "d":
         maxDenom = getMaxDenomFromUser()
         if maxDenom == 0:
             break
         bestNum, bestDenom, leastError = bestFracForMaxDenom(decimal, 
maxDenom)
         print "\n For a decimal of %s, %d/%d," % (str(decimal), bestNum, 
bestDenom)
         print "which is equal to %s, is the closest fraction" % 
(str(float(bestNum)/bestDenom))
         print "up to a maximum denominator of %d" % maxDenom
         print "Error is %.13e percent" % (leastError * 100)
         print "====================================="
         print

     else:
         minimumError = getMinimumErrorFromUser()
         if minimumError == 0:
             break
         num, denom, error = bestFracForMinimumError(decimal, minimumError)
         print "\n For a decimal of %s, %d/%d," % (str(decimal), num, denom)
         print "which is equal to %s, is the closest fraction" % 
(str(float(num)/denom))
         print "with smallest denominator and error <= %.13g percent" % 
minimumError
         print "Actual error is %.13e percent" % error
         print "============================================"
         print
exit()
===========end fraq.py=========================



More information about the Tutor mailing list