Arithmetic Operations

Python can be used to perform calculations involving addition, subtraction, multiplication, and division, as well as other types of artihmetic operations. These are some of the most fundamental types of commands that Python is able to process. We will discuss several of these operations in this chapter.

Addition and Subtraction

Perhaps unsurprisingly, our discussion of mathematical operations will begin with addition and subtraction.

Addition

Addition in Python is performed by placing the plus symbol (+) between two numbers. In the cell below we provide an example of using Python to perfom addition.

print(4.2 + 3.7)
7.9

Subtraction

We can also perform subtraction in Python. This is accomplished by placing a hyphen character (-) between two numbers. An example is provided in the code cell below.

print(3 - 15)
-12

Multiplication and Division

Moving on from addition and subtraction, we will now consider the multiplication and division operations.

Multiplication

Multiplication in Python is performed by placing an asterisk character (*) between two numbers. We demonstrate this in the next cell.

print(6 * 7)
42

Division

Division is peformed by placing the forward slash character (/) between two numbers. The next three cells provide examples of division.

print(5 / 2)
2.5
print(8 / 2)
4.0
print(7 / 3)
2.3333333333333335

The operation 7 / 3 in the preceding cell results in a repeating decimal. Python (like any other programming language) is not capable of storing real numbers to infinite precision. Numbers with non-terminating decimal expansions must be rounded to a specific finite precision.

You may notice that there is something unusual about how Pyhon rounded the final digit of the result in the cell above. We will address this issue later in the section Floating-Point Representation.

Division by Zero

If we attempt to divide by zero, we get an error.

42 / 0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-7-52cebea8b64f> in <module>
----> 1 42 / 0

ZeroDivisionError: division by zero

Errors are an ever-present part of any programmer’s existence. Every error results in an error message that attempts to explain what caused the error. Note that the last line in the output above says:

ZeroDivisionError: division by zero

This is Python’s way of telling us that we got an error because we attempted to commmit the mathematical sin of dividing by zero. Error messages are often cryptic and difficult to interpret, but it is important that you attempt to understand what any error messages you encounter are trying to tell you. Being able to read error messages can be a big help when attempting to debug your code.

You can find more information about error messages in the Error Messages page in the glossary.

Exponentiation

In this section, we will discuss how to use Python to perform exponentiation.

Exponentiation

Python uses two asterisks (**) to indicate the operation of exponentiation. In the next cell, we will calculate 3 raised to the 5th power, or \(3^5\).

print(3 ** 5)
243

Note about Exponentiation Operator

Many programming languages and computer algebra systems use the “carat” symbol (^) for exponentiation. Python is somewhat unusual in its use of ** for exponentiation. However, even if you are familiar with using ^ to indicate exponents, you will likely get used to Python’s way of doing things quickly.

Be careful, though. Python does use the carat operator, but to indicate a different operation called bitwise XOR. This can be something of a pitfall because if you typed 3 ^ 5 in an attempt to calculate \(3^5\), you would NOT get an error message, but you would get the incorrect answer (try this on your own). If you didn’t realize that your answer was wrong, that could cause some problems for you down the road.

Negative Exponents

We can use negative exponenents when performing calculations in Python. Recall that the mathematical expression \(x^{-n}\) is defined by \(x^{-n} = \frac{1}{x^n}\). In the next cell, we will calculate \(5^{-2}\), which is equal to \(1/25\).

print( 5 ** -2 )
0.04

Calculating Roots

We can use exponents to calculate roots. Recall that the \(n\)th root of a number can be calculated by raising that number to the power \(1/n\). In other words, \(\sqrt[n]{x} = x^{1 / n}\).

As an example, we will now calculate the square root of 81. Note that \(\sqrt{81} = 81^{1/2} = 81^{0.5}\).

print(81 ** 0.5)
9.0

In the next cell, we will calculate the fourth root of 37.

print(37 ** (1/4))
2.4663257145596607

Warning About Parentheses

Notice that we placed parentheses around the fraction 1/4 in the code cell above. It is important for us to do so. Python respects the standard mathematical order of operations. If we did not include the parentheses, then Python would have raised 37 to the power of 1 and then divided the result by 4. In summary:

  • The Python expression 37 ** 1/4 would calculate the value of \(\frac{37^1}{4} = 9.25\).

  • The Python expression 37 ** (1/4) would calculate the value of \(37^{1/4} = 2.4663257145596607\).

We will discuss order of operations in more detail in the next section.

We can avoid the need for parentheses in the previous code cell by replacing the fractional exponent with its decimal representation. This is illustrated in the next cell.

print(37 ** 0.25)
2.4663257145596607

Order of Operations

The value of a mathematical expression can be dependent on the order in which you perform the operations that constitute that expression. To avoid ambiguity or the need for excessive use of parentheses, mathematicians have adopted a standard order of operations that should be followed when evaluating expressions. Python aheres to these same rules when evaluating expressions.

PEMDAS

The order of operations is often summarizued using the acronym PEMDAS. The meaning of this acronym is explained below.

  • (P)arentheses. Calculate the value of any expression appearing within a set of parentheses before performing calculations that involve that expression.

  • (E)xponentiation. Perform calculations involving exponentiation before moving on to other operations.

  • (M)ultiplication and (D)ivision. Perform calculations involving multiplication and division before those involving addition or subtraction.

  • (A)ddition and (S)ubtraction. Perform calculations involving addition and subtraction last.

In the next cell, we will demonstrate that Python does indeed perform multiplication prior to addition.

print(4 + 5 * 6)
34

If we wished for the addition to be performed before the multiplication in the expression above, then we could add parentheses to the expression. This is demonstrated below.

print((4 + 5) * 6)
54

We can combine parentheses and operations to form complex arithmetic expressions.

print( (1 + 4) * (3 + 8 / 2) ** 2 )
245.0

Modulus and Floor Division

In this section, we will discuss the modulus and floor division operations. Both of these operations are related to the process of dividing one integer by another.

The Modulus Operation

The modulus operation yields the remainder obtained from dividing one integer by another. It is performed in Python by placing the percent character (%) between two integer values. The number on the left of the % symbol is divided by the one on the right, and Python reports back the remainder of this division.

Let’s consider a few examples. We will start by calculating the remainder obtained when dividing 8 by 3.

print(8 % 3)
2

In the next example, we will calculate the remainder of 25 divided by 7.

print(25 % 7)
4

As our last example of the modulus operation, we will calculate the remainder of 90 divided by 3. Note that since 90 is divisible by 3, we get a remainder of 0.

print(90 % 3)
0

The modulus operator has many useful applications in programming, some of which we will explore in later chapters.

Note

The symbol used to indicate the modulus operation varies from one programming language to another. Several programming languages use %, as Python does. But it is also common to see %% or mod used to indicate this operation.

Floor Division

The floor division operation is related to the modulus operation in that it is obtained through the process of integer division. However, floor division reports back the quotient of the division rather than the remainder. We use double slashes (//) to perform floor division in Python.

We will illustration floor division using the same examples we considered for the modulus. We will start with 8 divided by 3.

print(8 // 3)
2

Next, we will calculate the quotient resulting from dividing 25 by 7.

print(25 // 7)
3

We conclude the section by calculating the quotient of 90 divided by 3.

print(90 // 3)
30

Note

When writing code, there are often many different ways to obtain a particular result. We can also perform floor division using the int() function. This function returns the whole number (or integer) part of a decimal number. As a consequence, the following two expressions will generate the same value:

25 // 7
int(25 / 7)

Although the int() function can be used for floor division, it has additional uses that we will explore later.

Floating-Point Representation

In this section, we will discuss a commonly-occurring phenonmenon in which Python seemingly misrepresents the value of certain decimal numbers. Recall that a floating-point value is a numerical value that contains a decimal point. For example, each of the following values are floating-point values:

3.14159, 4.5, 2.3333333, 19.0

We have seen examples in previous sections where Python seems to make very small rounding errors when providing the result of calculations involving floating-point values.

For example, consider the result obtained from dividing 7 by 3.

print(7 / 3)
2.3333333333333335

The exact value of \(7/3\) is \(2.3333...\), with the threes in the fractional part continuing on forever. Computers are not typically capable of storing decimal values with infinite precision, and thus Python (and other programming languages) are forced to round non-terminating decimal values. However, you would expect that the last digit of the rounded result would be a 3 rather than a 5. It would seem that Python is making a rounding error.

This issue is perhaps demonstrated more strikingly in the next example, in which we add 0.1 and 0.2.

print(0.1 + 0.2)
0.30000000000000004

You would obvsiously expect the result of the calculation above to be 0.3, but Python reports a result that is very, very slightly larger. This is particularly strange considering that you would likely not expect this calculation to involve any rounding at all!

Binary Representation

These unexpected results stem from the fact that computers internally represent numbers in a base 2 (binary) number system rather than the base 10 (decimal) system that modern humans are more familiar with. We will not delve into the details of exactly why binary representations sometimes yield unexpected results when working with floating point numbers, but suffice it to say that tiny rounding “errors” can occur when converting a number from base 10 (as it appears on the screen) to base 2 (as it is stored by the computer), and vice-versa. You can read more about this topic here: Floating-Point Error in Python.

Rounding Floating Point Values

Understanding that operations involving floating-point values might occasionally result in tiny rounding errors, the question remains: What do we do about it? In most cases, the answer is simple: Nothing. If you are using the result of such a calculation in another calculation, the discrepency between the actual value and the calculated value is so small that it is unlikely to be relevant.

If you are displaying the value as a final result and find the incorrectly rounded result to be displeasing, then you can simply round the displayed result to any precision that is less than what was used to store the number. To see an illustration of this, we will again perform the calculation 0.1 + 0.2, but will this time round the result to 10 decimal places.

print(round(0.1 + 0.2, 10))
0.3

The key point to take away from this discussion is that you should understand that there is always a chance that a floating-point operation might produce a result that is slightly different from (but very close to) the exact result.