Skip to content

Week 2: math and errors

This week has real Python in it, so these exercises are no longer about the tools. Every one of them is the same four-part shape you built in the labs: read some input, convert it to the type you need, calculate a result, and print that result in a required format.

Save each program in the Week02 folder inside ~/CS149, and commit and push your work when you finish. The exercises are ordered from easiest to hardest, and each one has an assignment on Gradescope so you can check your own work as you go. Once you have finished the style lab and have ruff installed, run ruff check on each of these before you call it done.

Ex2.1 Twelve Dozen

When used as a noun, a gross is a quantity equal to 12 dozen, or 144.

Write a program named gross.py that reads a number of gross from the user and reports how many items that is. Use exactly the prompt "How many gross? ".

How many gross? 2
2 gross is 288 items

Run it a second time and enter 100, which should report 14400 items.

input() always returns a string

If you multiply what input() hands you, you will not get the answer you expect. Convert it first, either in two steps or in one:

count = input()        # a string
count = int(input())   # an integer

Ex2.2 Average Price

Your boss at Amalgamated Sales is wary of complex mathematical topics such as division, and has asked you to write the program that works out what a single item cost.

Write a program named average.py that reads the name of an item, the number of them purchased, and the total price paid in whole dollars, in that order. Calculate the average price per item, store it in a variable, round it to two decimal places, and print it. Use exactly the prompts shown below.

Enter the item name: banana
Enter the number purchased: 100
Enter the total price: 153

The average price of a(n) banana is 1.53 dollars

The three values are three different types: the name is a string, the number purchased is an integer, and the total price is an integer number of dollars. Only one of the three needs no conversion at all.

Two decimal places is not the same as two digits

Run your program again with a total price of 150, and the average comes out as 1.5 rather than 1.50. That is not a bug in your program or in round(). A trailing zero is not part of a number's value, so rounding can never produce one. Week 3 gives you a tool that controls how a number is displayed, which is a different job; for now, 1.5 is the right answer.

Ex2.3 Round Numbers

Write a program named circle.py that reads the radius of a circle and reports its area and its circumference, each rounded to two decimal places.

Enter the radius: 3

Area: 28.27
Circumference: 18.85

A radius can be a measurement like 2.5, so convert it with float() rather than int(). Run your program a second time with a radius of 1, which should report an area of 3.14 and a circumference of 6.28.

Two things you have to look up, and one you don't

The value of pi is in the math module, so your program needs an import statement on its first line. Remember that math.pi is a value rather than a function, so it takes no parentheses.

You need the radius multiplied by itself for the area. Python has an operator for exponents and Week 3 introduces it, so for now write radius * radius.

Ex2.4 Absolute Path

Every output you have printed so far put a single space between one value and the next, because that is what print() does when you separate its arguments with commas. A path has no spaces in it, so this exercise cannot be done that way.

Write a program named path.py that reads a username and a folder name, then prints the absolute path of that folder in the user's home directory.

Enter your username: mayfiecs
Enter a folder name: Week02

Full path: /home/mayfiecs/Week02

Produce the last line of output with two print statements. Use one of the two settings you met in the lab to print Full path: without ending the line, and the other to join the parts of the path with / instead of a space.

One separator, three slashes

The path has three slashes in it, and you only get to write one separator. The trick is what you hand to print as its first argument.

Ex2.5 Repair Shop

The three previous exercises asked you to write a program that works. This one asks you to fix one that does not, which is a different and equally important skill.

Below is a program that was supposed to convert miles into kilometers. Save it into your Week02 folder as miles.py, exactly as it appears here, mistakes included.

miles = input("Enter a distance in miles: ")
totalKm = miles * 1.60934
print("That is", round(totalKm, 2) "kilometers")

It has four problems: one that Python catches before the program runs, one that happens while it runs, and two that ruff reports about a program that would otherwise work. Before you change anything, write down all four and decide which kind each one is. Then fix them. Both of the problems ruff reports are ones you already fixed once in payroll.py during the style lab.

When you are finished, the program should behave like this, and ruff check miles.py should report nothing at all.

Enter a distance in miles: 26.2
That is 42.16 kilometers

Run it a second time with 100 miles, which should report 160.93 kilometers.

Fix them in the order Python tells you

You cannot see three of these problems while the first one is still there. Python refuses to run a file it cannot read all the way through, so the error it catches before running hides everything that would have happened during the run. Fix what Python reports, run it again, and see what the program tells you next. Working one message at a time is how debugging actually goes, and it is faster than trying to spot everything at once.

Ex2.6 Counting Bits

A bit is a single binary digit, 0 or 1. With two bits you can write exactly four different sequences, and with three bits you can write eight:

000  010  100  110
001  011  101  111

Now go the other way. If you need to represent 5 different values, how many bits does that take? Two bits are not enough, since two bits only give you four sequences, so the answer is 3.

In general, the number of bits needed to represent \(n\) different values is \(\lceil\log_2{n}\rceil\), read as "the ceiling of the log base 2 of \(n\)." The ceiling of a number is the nearest integer greater than or equal to it, which is what turns \(\log_2{5}\), roughly 2.32, into 3 rather than 2.

Write a program named bits.py that reads how many values are needed and reports how many bits that takes.

How many values do you need? 5
You need 3 bits to represent 5 values

Both the ceiling function and the logarithm are in the math module, and neither one is something you are expected to have memorized. The math module documentation is where you find them, and finding them there is half the exercise.

Run your program with 8, which needs 3 bits, and with 9, which needs 4.

Two ways to take a log base 2, and one of them is better

The log function in the math module uses base \(e\) unless you tell it otherwise, and you can pass it a base as a second argument. There is also a function that does base 2 and nothing else. Prefer the second one. Computing a logarithm in an arbitrary base involves a division that can land a hair above a whole number, so a power of two occasionally comes back as 29.000000000000004, and a ceiling turns that hair into a whole extra bit.

An edge case worth a moment

Try running your program with 1. Your program reports that you need 0 bits, and by the formula that is correct: with zero bits there is exactly one thing you can write, namely nothing at all. Whether that is a useful answer depends on what you were going to do with it. Nothing needs fixing here; noticing it is the point.

When you're done

Commit and push your Week02 folder:

git add -A
git commit -m "Add week 2 practice programs"
git push

Every program in this set produces exact output, and every one of them can be run again with different input. Before you move on, run each one at least twice with different values, and once with input you expect to break it. Predicting what a program will print before you run it, and predicting which kind of error a bad input will produce, is exactly what Quiz 1 asks you to do on paper.