Chapter 4

Math Operators

Subsections of Math Operators

Numeric Data

YouTube Video

Resources

Previously, we learned about strings and string values in pseudocode. Recall that a string is just text inside of a set of quotation marks "", such as "Hello World" or "Willie Wildcat". In technical terms, a string is an example of a data type in programming. A data type defines the way a particular value can be stored in a computer. For text values, we use the string data type.

What about numbers? We all know how important numbers can be, especially since we’ve probably spent more time studying mathematics than just about any other subject in school. So, let’s introduce a new data type in pseudocode called the number data type. This data type can store any single number, such as $1$ or $2.3$ or even special numbers like $\pi$ (pi) or $e$ (Euler’s number).

So, to create an expression that evaluates to a numerical value in pseudocode, we can just use the numbers in our code instead of text in quotes. For example, to store the number $7$ in a variable, we’d use the following assignment statement in pseudocode:

num1 <- 7

Notice that the numerical value 7 in our code does not have quotation marks around it. This is because we want to treat it like a numerical value instead of a string.

Also, recall from earlier that we cannot use a number as the first symbol in a variable name? This is because numerical values must always start with a number, so we enforce this rule to allow us to tell the difference between numerical values and variable names.

For a number with a decimal in it, such as $1.23$, we can use a similar process:

num2 <- 1.23

If we have a value that is less than $1$, we must put a 0 in front of the decimal point, like this:

num3 <- 0.42

We can also create negative values by placing the negative symbol - (the same symbol as the minus sign) in front of the numerical value:

num4 <- -4.56

Notice that we have to be careful to include a space between the arrow symbol <- in the assignment statement and the negative symbol - for a negative value.

As we can see, creating variables that store numerical values is pretty easy, and it hopefully works exactly like you expect it to work.

Converting Between Data Types

Now that we have two different data types, strings and numbers, it might be useful to convert between the two data types. Officially, the AP Pseudocode does not include an explicit way to convert between data types, or any concept of different data types at all. Instead, they just assume that variables can “automagically” convert data as the developer intended, without performing any additional steps.

However, this can get a bit confusing, so we’ll briefly introduce two different procedures in pseudocode that can handle converting data between different types.

To convert any type of data to a number, we can use the NUMBER(expression) procedure. It will evaluate the expression to a value, and then convert that value to a number. Of course, this requires us to make sure that whatever value we get when we evaluate the expression will make sense as a number. Since we aren’t running this on a real computer, we don’t have to worry about any errors or crashes - instead, it will just mean that our program won’t make any sense when we try to run it on our “mental model” of a computer.

Likewise, to convert any data to a string, we can use the STRING(expression) procedure in a similar way. Thankfully, pretty much any value in any data type can be represented as a string in some way, so we don’t have to worry about this procedure causing issues if the expression results in a strange value.

Subsections of Numeric Data

Pseudocode Operators

YouTube Video

Resources

Now that we have the ability to store numerical data in variables in pseudocode, we should also learn how to manipulate that data into something new. To do that, let’s learn about operators. An operator in programming is a special symbol that can be used in an expression to manipulate the data in some way. Most operators are binary operators, which means they perform an operation that uses two values as input and produces a single value as output. In fact, in some programming languages, the operators themselves are implemented as procedures in the language!

An expression containing a binary operator typically follows this format:

<expression> <operator> <expression>

As before, the <expression> parts can be any valid expression in the language, and the <operator> part is typically a single symbol, but it can also be a short keyword as well.

Thankfully, these operators should all be very familiar to us from mathematics already, so this is just a quick discussion of how they can be used in programming.

Addition and Subtraction

For starters, we can use the plus + and minus - symbols as operators to perform addition and subtraction in pseudocode, just like in math. For example, we can add two variables together to create a third variable as shown in this example:

a <- 5
b <- 7
c <- a + b
DISPLAY(c)

When we run this code on our “mental model” of a computer, we should get this result:

12

Likewise, we can subtract two variables using the minus symbol - as shown here:

x <- 24
y <- 10
z <- x - y
DISPLAY(z)

This code should produce this output:

14

Multiplication and Division

In pseudocode, we use the asterisk *, sometimes referred to as the star symbol, to multiply two values together. For example, we can find the product of two values as shown in this pseudocode block:

a <- 6
b <- 7
c <- a * b
DISPLAY(c)

When we run this code, we should see the following result displayed to the user:

42

Division is performed using the slash / symbol. A great way to think of division in programming is just like a fraction, since it uses the same symbol between the two numbers. For example, if we execute this code:

x <- 27
y <- 3
z <- x / y
DISPLAY(z)

we would see this output:

9

What if the division would result in a remainder? In that case, we’ll simply use decimal values in pseudocode so that the result is exactly correct. For example, if we try to divide $19$ by $5$, as in this example:

a <- 19
b <- 5
c <- a / b
DISPLAY(c)

Our “mental model” of a computer would produce the following output:

3.8

So, as we can see, all of these operators in pseudocode work exactly like their counterparts in math. Even though we aren’t running our code on an actual computer, we should be easily able to use a simple calculator to help us perform these operations if needed.

Modulo Operator

There is one other operator that is used commonly in pseudocode - the modulo operator. The modulo operator is used to find the remainder of a division operation. If we think back to math again, we’ve probably learned how to perform long division when dividing two values. At the end, we might be left with a remainder, or a portion of the first number that is left over after the operation is complete. In many computer programs, that value is very useful, so we have a special operator we can use to find that value. In pseudocode, we use the keyword MOD as the modulo operator.

For example, if we want to find the remainder after dividing $19$ by $5$, we would use the following code:

x <- 19
y <- 5
z <- x MOD y
DISPLAY(z)

When we run this code, we would get the following output:

4

This is because the value $5$ will fit into the value $19$ only $3$ times, and then we’ll have the value $4$ left over. Mathematically, we are saying that $19 / 5 = (3 * 5) + 4$. Since $4$ is the leftover portion, it is the resulting value when we use the modulo operator.

In this course, we’ll only worry about how the modulo operator works when applied to positive whole numbers. In practice, it can be applied to any numerical value, including decimal values and negative numbers, but those values are not really useful in most cases. So, to keep things simple, we’ll only use positive whole numbers with this operator.

Order of Operations

Finally, just like in mathematics, we must also be aware of the order that these operators are applied, especially if they are combined into a single expression. Thankfully, the same rules we learned in mathematics apply in programming as well. Specifically, operators in pseudocode are applied in this order:

  1. Operations in parentheses are resolved first, moving from left to right.
  2. *, / and MOD are resolved second, moving from left to right.
  3. + and - are resolved third, moving from left to right.

In most cases, it is best to include parentheses whenever we include multiple operators on the same line, just so the intended interpretation is perfectly clear. However, let’s work through a quick example just to see the order of operations in practice.

Here’s a complex expression in pseudocode that we can try to evaluate:

x <- 8 / 4 + 5 * (3 + 1) - 7 MOD 4

Looking at our order of operations, the first step is to handle any expressions inside of parentheses. So, we’ll first start with the expression (3 + 1) and evaluate it to 4.

x <- 8 / 4 + 5 * 4 - 7 MOD 4

Then, we’ll go right to left and perform any multiplication, division, and modulo operations. This means we’ll evaluate 8 / 4, 5 * 4 and 7 MOD 4 and replace them with the resulting values:

x <- 2 + 20 - 3

Finally, we’ll perform addition and subtraction from left to right. So, we’ll evaluate 2 + 20 first, and then subtract 3 from the result of that operation. At the end, we’ll have this statement:

x <- 19

So, we were able to use our knowledge of the order of operations to evaluate that complex expression to a single value, $19$, which will be stored in the variable x.

Subsections of Pseudocode Operators

Integers & Floats

YouTube Video

Resources

So far, we’ve only worked with string values in Python. Strings are a very useful data type in programming languages such as Python, but they are very limited in their use. Recall that a data type simply defines how a particular value is stored in a computer. The str data type is used to store string values in Python.

Python supports many different data types for handling various data that we’d like to store and manipulate in our programs. In this lab, we’re going to cover the two basic types used for storing numbers in Python, the int or integer type, and the float or floating-point type.

Integers

In mathematics, an integer is a whole number, such as $3$, $-5$, or even $0$. Basically, any positive or negative number that doesn’t include a fractional or decimal portion is a whole number, and therefore it is an integer. In Python, those numbers can be stored in the int data type.

In Python, we can store an integer value in a variable using an assignment statement:

x = 5

That statement will store the integer value $5$ in the variable x. Notice that the value $5$ does not have quotation marks around it. This is because we want to store the integer value $5$ and not the string value "5" in the variable. Also, as we learned earlier, this is why we cannot create variable names that begin with a number - since numerical values start with a number, this is how Python can tell the difference between a numerical value and a variable.

Just like in pseudocode, we can also store negative numbers in a variable by placing a negative symbol - in front of the numerical value:

y = -8

We’ll need to be careful and make sure that there is a space after the equals sign =, but no space between the negative symbol - and the number after it. Otherwise, the negative symbol could be confused for the minus symbol, which is an operator that we’ll learn about later in this lab.

In Python, there is effectively no maximum size for an integer, so we can store any arbitrarily large whole number (either positive or negative) in an int variable.

Floating-Point values

The other type of number we can store in Python is a floating-point number. We won’t go into too much detail about floating-point values here, since you’ll learn about them elsewhere in this class. For the purposes of programming, the only thing to know about floating-point numbers is that they are used to represent numbers that include a fractional or decimal portion. In Python, these values are stored in the float data type.

To create a variable that stores a floating-point value in Python, we can use an assignment statement that includes a value with a decimal point, like this:

a = 5.8

We can also create negative values using the negative symbol -:

b = -7.987

Finally, it is possible to store a whole number in a floating-point value by simply adding a decimal point and a 0 at the end of the value, as in this example:

c = 42.0

Later in this lab, we’ll see a couple of situations where that may be useful.

For now, we’re just going to assume that Python can easily handle any reasonable number we want it to store in a float variable, but there are some limits to the size and accuracy of those numbers. To reach these limits, we usually have to be dealing with numbers that have $100$ or more digits, either before or after the decimal place. So, for the purposes of this class, those limits really won’t apply to what we’re doing. You’ll learn about these limits in detail in later programming classes.

Determining Variable Type

One thing that is very useful to know how to do in Python is determining the type of data stored in a variable. Python is very flexible, and we can store any type of data in any variable. In fact, a variable’s data type can even change in Python, which is something that many other programming languages won’t allow. Technically speaking, we would say that Python uses strong typing, which means that each variable has a known data type that we can find, and dynamic typing, meaning that the type of the variable can change while the program is running.

To determine the type of a variable, we can use the type(expression) function in Python. We can simply place any variable or expression in the expression argument, and then it will tell us the type of the value that results from evaluating that expression. Then, we can simply use the print() function to print it to the screen. We won’t use this in our programs themselves, but it can be helpful for debugging purposes or to just better understand what is going on with data types.

Here’s a quick example program showing the type() function in Python:

x = "Hello"
y = 5
z = 6.7
print(type(x))
print(type(y))
print(type(z))

When we execute this code in Python, we should see the following output:

<class 'str'>
<class 'int'>
<class 'float'>

Based on that output, we can assume that the variable x is the str data type for strings, y is the int data type for whole numbers, and z is the float data type for decimal numbers. The type() function is pretty handy!

Converting Between Data Types

We can also convert values between the various data types in Python. To do this, there are special functions that match the name of the data types themselves, just like we saw in pseudocode. So, to convert any value to a string, we can use the str() function. Likewise, to convert anything to an integer, we can use the int() function. And finally, to convert anything to a floating-point value, we can use the float() function.

So, we can extend the previous example a bit by showing how we can convert values between different data types:

x = "5.7"
print(x)
print(type(x))
print()
y = float(x)
print(y)
print(type(y))
print()
z = int(y)
print(z)
print(type(z))

When we run this program, we’ll get this output:

5.7
<class 'str'>

5.7
<class 'float'>

5
<class 'int'>

In this program, we’re starting with the string value "5.7" stored in variable x. So, the first two print() statements will print that string value, and show that x is indeed storing a str data type. Then, we’ll use the float() function to convert the string value "5.7" stored in x to the floating-point value $5.7$ and store that in y. The next two print statements will print that value, and show that y is storing a float data type. Notice that the value printed for both variables x and y looks identical, but the data type of each variable is different!

Finally, we can use the int() function to convert the floating-point value $5.7$ to an integer. In math, when we are asked to convert the number $5.7$ to a whole number, our first instinct is probably to just round up to $6$, since that is the closest value. However, in Python, as in most other programming languages, this function will simply truncate the value instead. Truncating a value simply means we take off the end of the value, so to convert $5.7$ to an integer we just remove the decimal portion, and we’re left with the value $5$. So, in the output above, we see that z stores the integer value $5$, and it is the int data type.

Notice that we are careful to say that the int() function will truncate the value, and not that it will round down. This is due to how Python handles negative numbers like $-5.7$. When converting that to an integer, it will also truncate it to $-5$ instead of rounding down to $-6$. So, we use the word truncate as the best way to describe the int() function.

Exceptions

Since we are running our Python programs on a real computer, we have to be a bit careful about how we use these functions. Specifically, if we try to convert a value to a different data type and Python can’t figure out how to do that, we’ll cause an exception to occur. An exception in programming is any error that happens when the computer tries to run our code.

For example, what if we try to convert the string value "5.7" directly to an int data type, as in this example:

a = "5.7"
print(a)
print(type(a))
print()
b = int(a)
print(b)
print(type(b))

When we try to run this code in a file, such as the tutor.py file shown here, we’ll see this output printed on the terminal:

5.7
<class 'str'>

Traceback (most recent call last):
  File "tutor.py", line 5, in <module>
    b = int(a)
ValueError: invalid literal for int() with base 10: '5.7'

Uh oh! That’s not good. In the output, we can see that we’ve caused a ValueError, which is an exception that happens when we try to use a value in an incorrect way. So, we’ll need to carefully look at our code to see if we can find and fix the error.

Thankfully, in the output, it will tell us that the error occurred on line 5 of the file tutor.py, so we can open that file and scroll to that line of code:

b = int(a)

This is where the error occurred. There are several ways we can fix it. The easiest would be to simply convert a to a floating-point value using the float() function instead.

Learning how to find and fix these exceptions is a key part of learning how to program. We’ll inevitably run into a few exceptions as we start to build larger and more complex programs. In this course, most exceptions can be easily handled simply by working carefully through the code, but every once in a while we may run into an exception that is truly difficult to solve. That’s one of the important things to remember when learning how to program - it is sometimes much easier to cause an exception than it is to figure out how to fix it, and sometimes you may need to reach out for help to get past a particularly tricky exception. So, don’t be afraid to ask the instructors or TAs for help if you get stuck on an exception. Many times, it’s a great chance for you to learn some new programming skills.

Subsections of Integers & Floats

Python Operators

YouTube Video

Resources

We can also use Python to perform mathematical operations on numerical data using operators. So, let’s briefly review the operators we’ve learned so far, and introduce a couple of new operators that are unique to Python.

Mathematical Operators

Python supports the same mathematical operators that we’ve already seen in pseudocode. The only exception is the the modulo operation is performed using the percent symbol % instead of the MOD keyword. So, here are the symbols we can use in Python and the operations they perform:

  • + addition
  • - subtraction
  • * multiplication
  • / division
  • % modulo

However, there is one major difference between how these operators work in pseudocode and how they work in Python, and it has to do with the fact that Python includes two numerical data types. To deal with this, we have to define how the operators work when applied to different data types.

Resulting Data Types - Same Type

The basic rule to remember, if a mathematical operator is applied to two variables of the same data type, the result will also be that data type.

Let’s see what that means in practice. Here’s a quick example in Python using the multiplication operator on two integer values:

x = 5
y = 10
z = x * y
print(z)
print(type(z))

When we run this code, we should see the following output:

50
<class 'int'>

Since both x and y are the int data type, the result of x * y will also be an int value, so the variable z will have that data type, as shown in this example.

However, there is one exception to this rule, which is the division operator /. In Python, the division operator will always return a float value, even if it is a whole number. Here’s an example that demonstrates that:

a = 9
b = 3
c = 4
x = a / b
print(x)
print(type(x))
print()
y = a / c
print(y)
print(type(y))

When we run this program, we’ll see the following output:

3.0
<class 'float'>

2.25
<class 'float'>

So, as we can see, even though we are dividing two int values, we’ll get a float value as a result each time we use the division operator.

Following the rule above, if we perform a mathematical operation between two float values, the resulting value will always be a float as well:

a = 2.5
b = 4.5
c = a + b
print(c)
print(type(c))

Running this code will produce this output:

7.0
<class 'float'>

So, even though the result is a whole number, the value that is stored is the float data type.

Resulting Data Types - Different Type

The other rule to remember is anytime an operation involves a float value and an int value, the result will be a float. So, if there are mixed types, Python will default to the float data type.

This can be seen in the following example:

a = 5
b = 2.0
c = a - b
print(c)
print(type(c))

When this code is executed, the output should look like this:

3.0
<class 'float'>

Once again, even though the result is a whole number, because the variable b is a float value, the entire result will also be a float value.

New Operators

In Python, we can also introduce two new operators:

  • ** exponentiation (power)
  • // integer division

First, the double star ** operator is used to represent the exponentiation operation, sometimes referred to the power operator. In Python, the expression 2 ** 3 would be written mathematically as $2^3$, which is the operation of taking $2$ to the power of $3$, or multiplying $2$ by itself $3$ times. This operator follows the rules listed above for determining what type of data is the result of the operation.

Here’s a quick example of using the ** operator in code:

x = 5 ** 3
print(x)
print(type(x))

When this code is run, we see the following output:

125
<class 'int'>

The integer division operator, represented by two forward slashes //, is used to perform division that truncates the result to an integer. However, it still follows the rules for determining the data type of the result as listed above, so if either of the values in the operation is a float value, it will return a float, even though the result is an integer.

Let’s look at an example with that operator in code:

a = 17.5 // 4.5
print(a)
print(type(a))

As we expect, when we run this program, we’ll get the following output:

3.0
<class 'float'>

So, we see that this operator will return a float value, even though it is truncating the result to an integer, simply because the input values contained a float.

Learning the data types that are returned by a mathematical operator can be tricky, but most programmers slowly develop an intuition of how each operator works and what to expect. So, don’t worry too much if this is confusing right now, since it will become much clearer with practice! Also, don’t forget that we can always create a simple test program like the examples shown above to confirm the result for any operation.

Order of operations

Let’s quickly review the order of operations in Python. Thankfully, this is very similar to what we’ve already seen in pseudocode and in mathematics - we just have to add the two new operators:

  1. Operations in parentheses are resolved first, moving from left to right.
  2. ** is resolved second, moving from left to right
  3. *, /, // and % are resolved third, moving from left to right.
  4. + and - are resolved fourth, moving from left to right.

Of course, this means that there are now 4 operators that all fit in the “multiplication and division” portion, so we have to carefully make sure they are all taken care of in the correct way. As we learned before it is always best to add extra parentheses to any expression to make the intent very clear instead of relying on the order of operations.

Subsections of Python Operators

Summary

In this lab, we covered several major important topics. Let’s quickly review them.

Data Types in Pseudocode

  • string data type stores text. Use STRING(expression) to convert an expression to a string if possible.
  • number data type stores numbers. Use NUMBER(expression) to convert an expression to a number if possible.

Math Operators in Pseudocode

  • + Addition
  • - Subtraction
  • * Multiplication
  • / Division
  • MOD Modulo (the remainder of division)

Pseudocode Order of Operations

  1. Parentheses
  2. Multiplication, Division and Modulo from left to right
  3. Addition and Subtraction from left to right

Data Types in Python

  • str data type stores text (strings). Use str(expression) to convert an expression to a string if possible.
  • int data type stores whole numbers (integers). Use int(expression) to convert an expression to an integer if possible.
  • float data type stored decimal numbers (floating-point). Use float(expression) to convert an expression to a floating-point value, if possible.

Math Operators in Python

  • + Addition
  • - Subtraction
  • * Multiplication
  • ** Exponentiation (Power)
  • / Division
  • // Integer Division
  • % Modulo (the remainder of division)

Python Order of operations

  1. Parentheses
  2. Exponentiation
  3. Multiplication, Division, Integer Division, and Modulo from left to right
  4. Addition and Subtraction from left to right