Skip to content

Calculating with Input

So far you have written programs that read a value with input() and display a value with print(). There is a catch in that pattern, and it causes more confusion in this course than anything else: input() always returns a string, even when the person at the keyboard types digits. A program that tries to calculate with a value straight from input() gets an error rather than a number.

Today you'll fix that problem for good by converting values from one type to another. You'll also use functions that Python does not know about until your program asks for them, and you'll write a complete program of the shape you'll use all semester: read some input, convert it, calculate a result, and print that result in a required format.

Step 1: Make a folder for this week's work

From now on, each week's programs live in their own folder inside ~/CS149. Open your operating system's file manager (Finder on macOS, File Explorer on Windows, Files on Linux) and navigate into ~/CS149. Create a new folder there named Week02, spelled exactly that way with a capital W and a leading zero before the 2. Save every program you write in this lab into that folder.

Why a folder per week?

By the end of the semester, your ~/CS149 folder would hold dozens of loose files if every program sat at the top level. One folder per week keeps related programs together and makes an old program easy to find again.

Step 2: Convert what input() gives you

Open Thonny and type the following two lines in the Shell, pressing Enter after each one. When Python asks for a number, type 10.

>>> side = input("Enter a number: ")
>>> side * 2

The Shell displays '1010', not 20. The quotation marks are Python telling you that the result is a string: side holds the two characters 1 and 0, not the number ten, so * 2 produced two copies of those characters rather than doubling a number.

Now ask Python to divide the same value:

>>> side / 2

This time Python reports a TypeError, because dividing a string by a number has no meaning at all.

Name the error, every time

The type of an error is the first word of the last line of the error message. Get in the habit of reading that word before anything else, because the type tells you what kind of mistake you made. A quiz can ask you to name the type of error a program produces, so the name matters as much as the fix.

Converting a value

The fix is a type conversion: a function that takes a value of one type and returns a value of another type. The function int() returns an integer, and the function float() returns a floating-point number.

>>> side = int(side)
>>> side * 2
>>> side / 2

Now side * 2 displays 20, and side / 2 displays 5.0. The / operator always produces a floating-point number, which is why the result has a decimal point even though ten divides evenly by two.

Converting in a second step, the way you just did, works fine. Most programs convert immediately instead, so that the variable holds a number from the very beginning:

side = int(input("Enter a number: "))

Read that line from the inside out. input() runs first and returns a string, then int() converts that string into an integer, and finally the assignment stores the integer in side. Both shapes are correct, and the single line is the one you'll write most often.

Predict, then check

Before you type anything for this part, write down what you expect each expression below to produce. Predicting first is the single most valuable habit you can build this semester, and a wrong prediction is more useful than a right one, because a wrong prediction has found you a real gap.

For each expression, write the value you expect and the type of that value. You can tell the three types apart from how the Shell displays a result: a string appears inside quotation marks, a floating-point number has a decimal point, and an integer has neither.

Expression Your prediction Actual
int("7")
float("7")
int("7.0")
int(3.7)
round(3.7)
round(3.14159, 2)
str(7)
int("twelve")

Now type each expression in the Shell and fill in the last column. If an expression produces an error rather than a value, write the type of the error.

Three of those results are worth stating plainly, because programs go wrong on all three:

  • int() truncates rather than rounds, so int(3.7) is 3. When you want the nearest whole number, round() is the function you want.
  • round() returns a different type depending on how you call it. With one argument it returns an integer, and with two arguments it returns a floating-point number, so round(3.7) is 4 and round(3.7, 2) is 3.7.
  • Converting text that does not spell a number fails, and so does int("7.0"), because 7.0 is not how an integer is written. When the text might contain a decimal point, convert it with float() instead.

int() on a string is not int() on a float

int(3.7) quietly throws away the fractional part and gives you 3. int("3.7") reports a ValueError instead. The difference is that the first conversion starts from a number and the second starts from text, and int() will only accept text that spells a whole number.

A curiosity about halves

What should round(2.5) be? Try both round(2.5) and round(3.5) in the Shell, and notice that the first gives 2 while the second gives 4. When a value sits exactly halfway between two whole numbers, Python rounds toward whichever neighbor is even, which spreads the rounding error in both directions instead of always pushing it upward. This behavior will not be on a quiz. It is here so that when a halfway value surprises you later, you know the computer is not broken.

Step 3: Use a function from a module

Every function you have used so far is built in, which means Python recognizes the name without being told: print(), input(), int(), float(), round(), str(), and abs() all work the moment Python starts. Not every function Python offers is built in. Try these two lines in the Shell:

>>> abs(-16)
>>> sqrt(16)

The first line displays 16. The second reports a NameError, which means Python does not recognize the name sqrt at all.

A square root function does exist. It just lives in a module named math, and Python keeps the contents of a module out of the way until a program asks for them. Asking is called importing:

>>> import math
>>> math.sqrt(16)

Now the square root arrives as expected. Notice that the name is math.sqrt, not sqrt: the math. in front is part of the name, and it tells Python which module to look in.

A module can hold values as well as functions. Try these two lines:

>>> math.pi
>>> math.sqrt(math.pi)

Parentheses mean 'call this function'

math.sqrt is a function, so math.sqrt(16) calls that function with the argument 16. math.pi is a value rather than a function, so math.pi needs no parentheses and takes no arguments. Writing math.pi() reports a TypeError, because a floating-point number is not something Python can call.

When a program file needs a module, the import statement goes at the very top of the file, above the rest of the code, so that every line below the import can use the module. You'll write your first import statement in a file in the next step.

There is much more in math

Nobody memorizes the contents of the math module, and you are not expected to either. You are expected to be able to look it up. The math module documentation lists everything the module contains. Import the module in the Shell and try three or four of its functions to see what each one returns.

Step 4: Write a complete program

Every program in this course follows the same four-part shape, and this is the step where you build it for the first time: read some input, convert it, calculate a result, and print that result.

The program you'll write measures a monitor. The size a manufacturer advertises, such as a "27 inch monitor," is not the width and not the height: it is the diagonal, measured corner to corner. Your program will read a width and a height and report both the diagonal and the aspect ratio.

Create a new file in Thonny and save it into your Week02 folder as monitor.py. Then write a program that does the following:

  1. Imports the math module, on the first line of the file.
  2. Reads a width in inches and a height in inches, converting each one with float() so that a measurement like 15.5 still works.
  3. Calculates the diagonal, which is the square root of the width times itself plus the height times itself.
  4. Calculates the aspect ratio, which is the width divided by the height.
  5. Prints the two results.

Print the results using print() with several arguments, the way you have already seen: print() puts a single space between one argument and the next, which is what produces the spacing in the required output below. A print() with no arguments at all prints a blank line, which is how you get the empty line after the prompts.

Run your program and enter a width of 12 and a height of 5. The output must match this exactly:

Enter the width in inches: 12
Enter the height in inches: 5

Diagonal: 13.0 inches
Aspect ratio: 2.4 to 1

Squaring a value

Multiply the value by itself: width * width. Python does have an operator for exponents, and Week 3 introduces it, so there is no need to reach for it yet.

Now try a real monitor

A 12 by 5 monitor is not a shape anyone sells, and those measurements were chosen to come out evenly. Run your program again with a width of 16 and a height of 9, which is the shape of most monitors and televisions sold today.

The two numbers your program prints are now unreadable, 18.35755975068582 and 1.7777777777777777. Both answers are correct, and neither is fit to show a person.

This is the job round() does. Round each of the two results to two decimal places before printing, and run the program a third time. With a width of 16 and a height of 9, the output must now match this exactly:

Enter the width in inches: 16
Enter the height in inches: 9

Diagonal: 18.36 inches
Aspect ratio: 1.78 to 1

Run the program once more with 12 and 5 and confirm that rounding did not disturb the first pair of results.

Step 5: Control your output exactly

Matching a required format exactly is a skill of its own, and it is easy to lose a point on a quiz for a space that should not be there. print() has two settings that control the spacing, and this step is where you meet both.

The setting named sep controls what print() puts between one argument and the next. Its default is a single space, which is why print("Diagonal:", 13.0, "inches") produces Diagonal: 13.0 inches even though your code contains no spaces inside the quotation marks.

The setting named end controls what print() puts after the last argument. Its default is a newline, which is why each print() starts a new line of output.

Predict what each of the five snippets below prints, and write your prediction down before you run anything. Pay close attention to where the spaces fall and where the line breaks fall.

(a)

print("Diagonal:", 13.0, "inches")

(b)

print("Diagonal:", 13.0, "inches", sep="")

©

print("width", "height", sep=" x ")

(d)

print("Loading", end="")
print("Done")

(e)

print("first")
print()
print("second")

Now type each snippet into a file and run it, or type it in the Shell, and compare the actual output against your prediction. Snippet (e) explains the blank line in your monitor program: a print() with no arguments has nothing to print, so all it produces is its end, which is a newline.

round() controls the number, not how the number looks

Ask Python for round(2.50, 2) and the answer is 2.5, so a program that rounds to two decimal places will still print 2.5 rather than 2.50. That is not a mistake in round(). A trailing zero is not part of a number's value, so no amount of rounding can force one to appear. Controlling the display of a number, including a fixed number of decimal places, needs a different tool, and Week 3 introduces it.

Step 6: Meet two kinds of errors

You have already produced several errors in this lab: a TypeError from dividing a string, a NameError from calling sqrt before importing math, and a ValueError or two from the prediction table. Every one of those errors has something in common. Python was already running when each one happened.

Not all errors are like that, and telling the two kinds apart is a Quiz 1 objective. The way to see the difference is to notice how far the program got before it stopped.

Both prompts appear, then the program stops

Run monitor.py and enter a width of 16 and a height of 0.

A monitor with no height is nonsense, but Python does not know that. Python happily reads both numbers, calculates the diagonal without complaint, and then stops with a ZeroDivisionError when it tries to divide the width by zero. Look at what appeared in the Shell before the error message: both prompts, with the values you typed. The program ran, did real work, and then failed partway through.

One error type inside another

ZeroDivisionError is one specific kind of ArithmeticError, which is the general name for an error in a calculation. Naming the specific type is what a quiz will ask for, so ZeroDivisionError is the answer to write down.

One prompt appears, then the program stops

Run monitor.py again, and this time enter twelve for the width.

Python reports a ValueError, and the message explains itself: the text 'twelve' could not be converted to a float. This is the error you will meet most often all semester, because it happens every time a person types something that is not a number into a program that needs one.

Look again at how far the program got. Only the first prompt appeared this time, because the program failed at the very first conversion and never reached the second input().

No prompt appears at all

Now break your program on purpose, and break the last line, as far from the beginning as you can get. Remove the comma after "Aspect ratio:" in the final print(), so that the line reads like this:

print("Aspect ratio:" ratio, "to 1")

Predict what will happen before you run the program. The broken line is the last line of the program, and every line above the broken line is still perfectly good code.

Run it.

Nothing happens. There is no prompt, no chance to type a width, and no output at all: only a SyntaxError and a highlighted line. Python reads the whole file and checks that it is valid Python before running any of it, so a mistake on the last line prevents the first line from ever running.

Repair your program before moving on

Put the comma back and run monitor.py once more to confirm it works, with a width of 16 and a height of 9. The version you commit in Step 8 must be the working one.

The two kinds

That is the whole distinction, and you have now seen it from both sides:

What you did Error type Which kind How far it got
Entered 0 for the height ZeroDivisionError Happens while it runs Both prompts
Entered twelve for the width ValueError Happens while it runs The first prompt
Left out a comma SyntaxError Caught before it runs Nothing at all

An error caught before your code runs means the file is not valid Python, so Python refuses to start. An error that happens while your code runs means the file was valid Python, and the trouble only appeared once a particular line actually executed, often because of a value the program was given.

A misspelled name is not a syntax error

Many students assume that any typing mistake is a SyntaxError, and that is worth correcting now. Misspell math.sqrt as math.sqrtt and Python will start your program normally, print any earlier output, and only then report an AttributeError. The file was valid Python; the name was simply wrong. That is why the NameError from sqrt(16) in Step 3 counts as an error that happened while the program was running, rather than one caught before it ran.

This course recognizes errors, it does not catch them

A textbook or an AI assistant may show you try and except, which are Python's tools for catching an error and continuing. CS 149 never uses them. Your job is to read an error, name its type, and understand what caused it.

Step 7: Write one on your own

You have a program of the four-part shape, so now write a second one without a walkthrough.

A ladder leans against the side of a building. The foot of the ladder rests on the ground some distance away from the wall, and the top of the ladder touches the wall somewhere above the ground. Given the length of the ladder and the distance from the wall to the foot of the ladder, your program reports how far up the wall the ladder reaches.

Save your program into your Week02 folder as ladder.py. Read two measurements in feet, convert them, calculate the height reached, round the result to two decimal places, and print it. Match this format exactly:

Enter the ladder length in feet: 13
Enter the distance from the wall in feet: 5

The ladder reaches 12.0 feet up the wall.

Test it a second time with a ladder length of 20 and a distance of 6, which should report 19.08 feet.

Draw the triangle first

Sketch the wall, the ground, and the ladder on paper before you write any code. The three sides of the triangle are the ladder, the distance along the ground, and the height up the wall, and the calculation depends entirely on which of the three is which. A sketch takes fifteen seconds and settles the question.

One more run

Run ladder.py once more with a ladder length of 5 and a distance from the wall of 13. Predict what will happen before you press Enter, then read the error message carefully.

That input describes an impossible ladder: no five foot ladder reaches a wall thirteen feet away. Python reports a ValueError, the same type of error you got from entering twelve earlier, for a completely different reason. The type alone was not enough to tell you what went wrong, and the message (math domain error) is what identifies the real problem. Read the message as well as the type, every time.

Step 8: Save your work with git

Your two programs are saved on this machine only. Commit them and send them to the shared repository with the same loop you have used since Week 1. Open a terminal, and from inside ~/CS149:

git status

Git lists your new Week02 folder as untracked.

git add -A
git commit -m "Add monitor and ladder programs"
git push

On your other machine, just pull

Do not rewrite these programs on your other machine. Open a terminal in ~/CS149 there and run git pull, and the Week02 folder with both programs will appear.

Summary

At the end of this lab you can build the program shape that the rest of the course rests on: read input, convert it to the type you actually need, calculate a result, and print that result in a required format.

Along the way you added four tools:

  • type conversion with int(), float(), str(), and round(), and the knowledge that input() always hands back a string,
  • import math, which reaches functions and values that Python does not recognize on its own,
  • sep and end, which control the spacing and the line breaks in your output, and
  • two kinds of errors, told apart by how far the program got before it stopped.

Every error you have met so far, of either kind, stopped your program. In the next session you will meet a third kind of problem that does not stop anything: the program runs, produces exactly the right answer, and there is still something wrong with it.