• Author: Paul Magwene
  • Title: Mathematical notation: sums and products
  • Date: 20 January 2016

Why mathematical notation?

When studying quantitative subjects like statistics, mathematics, or computer science, it's typical to use short hand notation to represent various operations. This is done because some operations are used so frequently that it would be tedious to write out a full explanation each time they're used.

Some of this mathematical notation can be a little intimidating at first. Don't let it scare you off. With a little practice it's easy to break the notation down into easy to understand parts.

Sum notation

Summing (adding things up) is something you do frequently in all sorts of quantitative fields.

When we carry out statistical analyses we're going to be working with sequences of numbers (mathematicians would usually call these vectors). In Python we might represent such a sequence as a list (or an array which we'll meet in a later class). In statistics we usually give the sequence a name like $\mathbf{x}$; when programming we might use a variable assignment like x = [3,1,4,...].

In mathematics we represent the operation of summing the elements of a sequence with a capital Greek letter sigma ($\Sigma$). Here's an example: $$ \sum_{i=1}^{10} \mathbf{x}_i $$

Notice that there are two numbers -- one above and one below the $\Sigma$. These are the upper and lower bounds of the indices of the elements we want from $\mathbf{x}$. Note that mathematicians index sequences from one, unlike computer scientists who usually index from zero.

In words, the above notation is equivalent to the written statement: "From the sequence we call $\mathbf{x}$, take the first 10 elements, and add them up."

An equivalent statement in Python would be:

sum(x[0:10])  # sum the first ten elements of x

Remember that when slicing Python sequences, the second part of the slice is non-inclusive (i.e. we take all the elements up to but not including the element indexed by 10).

Often it's convenient to further abstract our notation. Let's assume our sequence $\mathbf{x}$ has a length we'll call $n$. We don't necessarily know the length of $\mathbf{x}$ ahead of time, so using the label $n$ to refer to its length let's us abstract away this detail. If we want to represent the operation of summing up all the elements of $\mathbf{x}$ we could write: $$ \sum_{i=1}^n \mathbf{x}_i $$

The equivalent Python statement would be:

sum(x)  # sum all the elements of x

Notice that when using sum notation, the lower index doesn't have to start at 1. For example, to represent the operation of summing up the last 10 elements of $\mathbf{x}$ we could write: $$ \sum_{i = n-10}^n \mathbf{x}_i $$ The equivalent Python statement is:

sum(x[-10:])  # sum the last 10 elements of x

Summing with for loops

Python has a convenient sum function that makes it easy to quickly sum the elements of a sequence. But what if we didn't have this function, or what if we wanted to sum not the elements in the list, but rather some operation we applied to those elements? This problem is easy to solve with a for loop (Note: there are more efficient ways to do such operations, but we're aiming for conceptual simplicity). Let's illustrate this with an example:


In [1]:
x = [2,4,6,8,10]

s = 0  # initialize the object that will hold our sum
for i in x:
    s = s + i
    
print("The sum of x is:", s)


The sum of x is: 30

Instead of writing s = s + i we could have written s += i (read this as "s is whatever it was before plus the value of i"). So we could rewrite that for loop as:


In [5]:
x = [2,4,6,8,10]

s = 0  
for i in x:
    s += i
    
print("The sum of x is:", s)


The sum of x is: 30

Now what if we wanted to calculate the sum of the reciprocals of each element of x? A simple change to our code give us:


In [6]:
x = [2,4,6,8,10]
s = 0
for i in x:
    s += (1/i)
    
print("The sum of the reciprocals of x is:", s)


The sum of x is: 1.1416666666666666

To bring things full circle, the equivalent mathematical notation to represent the operation of summing the reciprocals of all the elements of $\mathbf{x}$ would be: $$ \sum_{i=1}^n \frac{1}{\mathbf{x}_i} $$

The code above is somewhat fragile in that it's not easily re-usable. What if we wanted to sum the reciprocals of a list called y or z instead of x? We'd have to go through our code example and change each instance of x. That's boring and error prone. Instead let's write a Python function to abstract away the steps:


In [11]:
def sum_of_reciprocals(x):
    s = 0
    for i in x:
        s += (1.0/i)
    return s

In [12]:
# test our function with different inputs
x = [2,4,6,8,10]
y = [1,3,5,7,9]
z = [-1,1,-1,1]

print("The sum of the reciprocals of x is:", sum_of_reciprocals(x))
print("The sum of the reciprocals of y is:", sum_of_reciprocals(y))
print("The sum of the reciprocals of z is:", sum_of_reciprocals(z))


The sum of the reciprocals of x is: 1.1416666666666666
The sum of the reciprocals of y is: 1.7873015873015872
The sum of the reciprocals of z is: 0.0

A even more compact way of writing our sum of reciprocals operation, that still used the built in sum function would be to use a list comprehension as shown below:


In [2]:
sum_recip_x = sum([(1.0/i) for i in x])
print("The sum of the reciprocals of x is: ", sum_recip_x)


The sum of the reciprocals of x is:  1.1416666666666666

Note that our sum_of_reciprocals function (or our solution using list comprehensions) doesn't deal with all possible cases we might use as input. If one of the elements of x was zero what would happen (go ahead and try it)? What if we passed a list of strings to the function instead of numbers?

Product notation

Now that you (hopefully) understand sum notation, it should be easy to understand product notation. We use product notation to represent the products of the elements of a sequence (i.e. the value we get when we multiply the elements of the sequence). As we'll see later in the course, product notation arises frequently in discussions of probability.

The mathematical shorthand for taking the product of a sequence of numbers is the capital Greek Pi ($\Pi$). In parallel to our first example above, the product of the first ten elements of a sequence $\mathbf{x}$ could be written this way: $$ \prod_{i=1}^{10} \mathbf{x}_i $$

Other than the use of $\Pi$ rather than $\Sigma$, this is identical to the sum notation above. As before the notation includes information about the upper and lower bounds of the element indices for which we want to apply the operation.

In a similar manner to what we saw before, we can represent the operation of getting the product of an arbitrary sequence $\mathbf{x}$ of length $n$ as follows: $$ \prod_{i=1}^{n} \mathbf{x}_i $$

Products with for loops

Unlike sum, there is no built-in product function in Python (we will see an efficient implementation of the product operation when we get to the numerical Python libraries). However, as we saw above we can use for loops to write our own product function.


In [17]:
def product(x):
    p = 1
    for i in x:
        p *= i # same as p = p * i
    return p

In [19]:
x = [2,4,6,8,10]
product(x)


Out[19]:
3840

In [20]:
product([(1.0/i) for i in x]) # use list comprehension to get reciprocals of x


Out[20]:
0.00026041666666666666