CS303E Homework 6

Instructor: Dr. Bill Young
Due Date: Friday, February 23, 2024 at 11:59pm

Practice writing Functions

Writing functions is a very useful programming skill. For each of the following functions, you should fill in the body of the function. I've done the first one for you. Each function should behave as indicated by the comment. At the bottom is a sample run showing how the functions are supposed to behave.

Note that some functions ask you to return a value, others to print something. Those are different behaviors and require different actions. Do what is asked.

You don't have to validate the type of inputs, but should test where required. For example, if the function takes as parameter a positive integer, you don't have to ensure that it's an integer; but you do have to check that it's positive. If an error occurs, print, don't return the error message. (See the discussion in the Programming Hints section below.) Don't return anything in such cases; the function will automatically return None.

Don't use recursion to solve any of these. We're not covering that until later in the semester. If you don't know what that means, that's fine!

Each function should have a descriptive comment. You can use or adapt my descriptions of the function for that purpose.

#----------------------------------------------------------------------
# 1. Write a function to return the sum of three numbers.  I did this
#    one for you.

def sum3Numbers (x, y, z):
    """Return the sum of the three parameters."""
    return x + y + z

#----------------------------------------------------------------------
# 2. Write a function to return the product of three numbers.

def multiply3Numbers( x, y, z ):

#----------------------------------------------------------------------
# 3. Write a function to return the sum of up to 3 numbers.  It should
#    accept 1, 2, or 3 parameters.  Hint: any parameter not given
#    defaults to 0.

def sumUpTo3Numbers (x, y = 0, z = 0):

#----------------------------------------------------------------------
# 4. Write a function to return the product of up to 3 numbers.  It
#    should accept 1, 2, or 3 parameters.  Hint: what should the
#    default be in this case?

def multiplyUpTo3Numbers (x, ... ):  # supply default args

#----------------------------------------------------------------------
# 5. Write a function that takes 2 numbers as input and prints them
#    out in ascending order.  Make sure it works if they are equal.

def printInOrder( x, y ):

#----------------------------------------------------------------------
# 6. Write a function that returns the area of a square, given the length of a side.
#    Print an error message if side is negative. 

def areaOfSquare( side ):

#----------------------------------------------------------------------
# 7. Write a function that returns the perimeter of a square, given
#    the length of a side.  Print an error message if side is negative.

def perimeterOfSquare( side ):

#----------------------------------------------------------------------
# 8. Write a function that returns the area of a circle, given the
#    radius.  Use math.pi. Print an error message if radius is negative.

def areaOfCircle( radius ):

#----------------------------------------------------------------------
# 9. Write a function that returns the circumference of a circle given
#    the radius.  Use math.pi. Print an error if radius is negative.

def circumferenceOfCircle( radius ):

#----------------------------------------------------------------------
# 10. Write a function: given parameters d1, d2, x, returns whether
#    both d1 and d2 are both factors of (evenly divide) x.  You can
#    assume all values are integers.

def bothFactors( d1, d2, x ):

#----------------------------------------------------------------------
# 11. Given a value x, compute and print out the area and circumference of a circle with
#    radius x and the area and perimeter of a square with side x.  Use your previous 
#    functions for these computations.  Leave a blank line above and below the printing.

def squareAndCircle( x ):

#----------------------------------------------------------------------
# 12. Write a function that returns the factorial of a positive
#     integer n.  Use a for loop to compute the factorial.  You can
#     assume the input is an integer, but print an error message if
#     it's not positive and return None.

def factorial( n ):

#----------------------------------------------------------------------
# 13. Write a function that returns the number of digits in the
#     decimal representation of a number n.  You can assume that
#     n is a positive integer.  E.g., numberLength( 12345 ) = 5.

def numberLength( n ):

#----------------------------------------------------------------------
# 14. Write a function that sums positive numbers entered by the user
#     and returns the sum.  You can assume that user inputs are
#     numbers (float or int).  If the number entered is negative, print 
#     an error message and continue;  don't add it to the sum.  There 
#     can be any number of inputs.  Stop when the user enters 0. 
#     (Note: This was a problem from Exam1 in an earlier semester.)

def sumPositiveNumbers():

#----------------------------------------------------------------------
Below is a run that shows the use of each of these functions. This is in interactive mode. To run the program in batch mode, you'd have to write test code with appropriate print statements. You don't need to turn in your test code, just a file containing your function definitions.

BTW: you'll notice that some of the floating point values are slightly off of the "correct" arithmetic answer. That's because, unlike integers, the representation of floats in the memory of the computer are approximate. What you're seeing is the result of rounding errors.

>>> from FunctionExamples import *
>>> sum3Numbers.__doc__                          # A reason to document your functions!
'Return the sum of the three parameters.'
>>> sum3Numbers( 5, 6, 7 )
18
>>> multiply3Numbers( 3.2, 6, -19.123 )
-367.1616000000001
>>> sumUpTo3Numbers( 12.9 )
12.9
>>> sumUpTo3Numbers( 12.9, 3 )
15.9
>>> sumUpTo3Numbers( 12.9, 3, 14.7 )
30.6
>>> multiplyUpTo3Numbers( 12.9 )
12.9
>>> multiplyUpTo3Numbers( 12.9, 3 )
38.7
>>> multiplyUpTo3Numbers( 12.9, 3, -2.7 )
-104.49000000000001
>>> printInOrder( 2.1, -10 )
-10 2.1
>>> printInOrder( 2.1, 10 )
2.1 10
>>> areaOfSquare( -10 )
Negative value entered
>>> areaOfSquare( 10 )
100
>>> perimeterOfSquare( -10.2 )
Negative value entered
>>> perimeterOfSquare( 10.2 )
40.8
>>> areaOfCircle( -10 )
Negative value entered
>>> areaOfCircle( 10 )
314.1592653589793
>>> circumferenceOfCircle( -10 )
Negative value entered
>>> circumferenceOfCircle( 10 )
62.83185307179586
>>> bothFactors( -2, 3, 20 )
False
>>> bothFactors( -2, 3, 30 )
True
>>> squareAndCircle( 10 )

Circle with radius 10 has:
   Area: 314.1592653589793
   Circumference: 62.83185307179586
Square with side 10 has:
   Area: 100
   Perimeter: 40

>>> factorial( -10 )
Input must be positive.
>>> factorial( 10 )
3628800
>>> numberLength( 21)
2
>>> numberLength( 1234567 )
7
>>> sumPositiveNumbers()
Enter a number: -10.4
Illegal input.
Enter a number: 10.4
Enter a number: 2.1234
Enter a number: 87
Enter a number: 0
99.5234
>>> sumPositiveNumbers()
Enter a number: 0
0
>>> sumPositiveNumbers()
Enter a number: -10
Illegal input.
Enter a number: 0
0
>>> 

Turning In the Assignment:

The program should be in a file named FunctionExamples.py. Submit the file via Canvas before the deadline shown at the top of this page. Submit it to the assignment hw6 under the assignments sections by uploading your python file.

Your file should run without errors. It must also contain a header with the following format:

# File: FunctionExamples.py
# Student: 
# UT EID:
# Course Name: CS303E
# 
# Date Created:
# Description of Program: 

Programming Tips:

Functions: Functions provide a powerful mechanism for abstraction. Once you've defined a function, it's as if you had an additional primitive in the programming language. For example, once we defined isPrime(n), you can treat that as it it were native to the language. Henceforth, whenever you need to check whether an integer is prime, you only need import that function from the appropriate library and call it. As long as you trust whomever programmed it, you really don't need to worry about how it works.

That's why it's a good idea to make your functions as robust as possible and thoroughly document their behavior. For example, our isPrime function works for arbitrary integers, but will crash for other inputs. For a production version, it would be better to validate the arguments more thoroughly. At very least, the program comments should make clear to any future user what assumptions you're making about the parameters.

Functions provide all of the following benefits:

  1. they provide reusable functionality;
  2. they make your programs easier to read;
  3. you only need to debug the code once;
  4. they make your program easier to maintain;
  5. they facilitate writing large programs;
  6. they support collaboration with a programming team.

New programmer giveaway: Often I see code that looks like this:

if condition:
   return True
else:
   return False
That's a dead giveaway that I'm dealing with an inexperienced programmer. Typically, condition in this Boolean context will be returning a Boolean (though not always; remember that any expression can be used in a Boolean context). If so, condition will evaluate to True or False. So why not just do this:
return condition
You'll get the same result; think about why that is! If condition doesn't return a bool and you need one, you can do:
return bool(condition)

BTW: if you're writing:

if condition:
   return False
else:
   return True
you can replace that with:
return not condition
That will always work, even if condition doesn't return a Boolean, since not always does.

Print vs. Return: Imagine a function plus(x, y) that adds two integers.

def plus( x, y ):
   return x + y
It wouldn't do you any good unless it could give the result back to its caller. That's what return does. Every function returns something; sometimes that is None. It's up to the caller what to do with the value it receives; often that's storing it into a variable.
x = 100
y = 200
answer = plus( x, y )
Following this, answer should contain 300. The call to plus will always compute and return an answer, but unless the caller (the program that invoked plus) "grabs it" somehow it's just lost.

If you invoke plus in interactive mode, the answer will be displayed, unless you save it.

>>> def plus(x, y): return x + y
... 
>>> plus( 100, 200 )
300
>>> answer = plus( 100, 200 )
>>> answer
300
>>> 
But in batch mode, you won't see the value displayed unless you explicitly print it.

If your program encounters some problem and you need to display an error message, you will typically print it, not return it. In this case, it's not a value you need to save or use in further computation; it's a message that you want the user to see. Of course, if the calling environment is expecting a value to be returned, you'll also have to deal with that. Remember that a function that doesn't explicitly return a value actually returns the value None, so the caller could handle that appropriately. Alternatively, the function could return some special "error" value that the caller can interpret appropriately. Most commonly, the function will "raise an exception" which can be caught and handled by the caller. We're not covering exception handling this semester.