Monday, February 16th, 2026¶

Last week, we began working with while loops and functions. We developed a function is_prime which takes in an integer n and returns True if n is prime and False otherwise.

In [1]:
def is_prime(n):
    n_is_prime = True

    for d in range(2,n):
        if n % d == 0:
            n_is_prime = False
            break
            
    if n_is_prime:
        return True
    else:
        return False
In [2]:
is_prime(11)
Out[2]:
True

Documenting code¶

When writing reports for this class (and when coding in general), it is important to explain your code to a potential reader so that they can follow along and understand what the code is doing and how it works. With Jupyter notebook, we have two main tools for documenting our code:

  • Writing explanations in Markdown cells that preceed each code cell;
  • Writing code comments directly within code cells.

Note: We will use both tools for every bit of code in our projects.

Explaining code through Markdown¶

We have previousy discussed working with Markdown cells. As a reminder, a cell can be converted to Markdown using the dropdown menu in the top toolbar or by selecting the cell and hitting the M key. We can then add plain-text to the Markdown cell, or other types of formatted text (e.g. bulleted lists, numbered lists, headings, etc.). To help us explain our code, there are some additional tools available in Markdown.

Italic and bold text¶

Italicized text can be written using asterisks * to enter and exit italic mode. For example, writing *This is italic text* in Markdown will produce: This is italic text. Similarly, bold text can be written using double asterisks ** to enter and exit bold mode. For example, writing **This is bold text** in Markdown will produce: This is bold text. We can also use triple asterisks to produce bold-italic text. We will often use either bold, italic, or both (depending on preference) to emphasize things like definitions in our reports.

Exercise: Write a Markdown cell that gives a definition of prime numbers.

A prime number is a positive integer greather than 1 that is divisible only by positive integers 1 and itself.

A prime number p is a integer greater than 1 that only has positive integer divisors 1 and p.

We call an integer p>1 a prime number if the only positive integer divisors are 1 and p.

Using LaTeX in Markdown¶

When explaining the mathematical ideas, it is helpful to be able to "write math". For example, we might like to write things like fractions, exponents, etc. and have them appear as one might write them on a piece of paper. One tool for accomplishing this is called $\LaTeX$, or LaTeX ("lay-tech").

In Markdown, we can enter and exit in-line LaTeX mode using dollar signs $. For example, consider the difference between the following Markdown and its rendering. For each example, we have entered and exited LaTeX mode to write out each number.

  • Plain-text:
    • 123456
    • 123^{456}
    • 123_{456}
  • $\LaTeX$:
    • $123456$
    • $123^{456}$
    • $123_{456}$

In our reports, we should always write math variables, equations, and expressions in LaTeX mode.

Exercise: Update your definition of prime numbers to make use of LaTeX where appropriate.

A prime number $p$ is an integer greater than $1$ that only has positive integer divisors $1$ and $p$.

We call an integer $p>1$ a prime number if the only positive integer divisors are $1$ and $p$.

Some common LaTeX commands:

  • Exponents: $x^2 + y^2$ renders as $x^2 + y^2$.
  • Fractions: $\frac{numerator}{denominator}$ renders as $\frac{numerator}{denominator}$.
  • Integrals and trig functions: $\int_0^x \cos(t) dt$ renders as $\int_0^x \cos(t) dt$.

Using a single dollar sign writes LaTeX in in-line mode (i.e. will appear within the same lines as the surrounding text). We can use two dollar signs ($$) to write in display mode, which gives a centered equation. For example, $$\int_0^x \cos(t) dt$$ renders as $$\int_0^x \cos(t) dt$$ whereas $\int_0^x \cos(t) dt$ renders as $\int_0^x \cos(t) dt$. Other common LaTeX commands: - Subscripts and superscripts: $a_n$, $2^n$ renders as $a_n$, $2^n$. - Square roots and other roots: $\sqrt{7}$, $\sqrt[10]{x^2-5}$ renders as $\sqrt{7}$, $\sqrt[10]{x^2 - 5}$. - Greek letters: $\alpha$, $\beta$, $\gamma$, $\sigma$, $\omega$, $\pi$ renders as $\alpha$, $\beta$, $\gamma$, $\sigma$, $\omega$, $\pi$. Examples: - Euler's formula: $$e^{i\pi} + 1 = 0$$ renders as $$e^{i\pi} + 1 = 0.$$ - Pythagorean theorem: $$\cos^2 \theta + \sin^2\theta = 1$$ renders as $$\cos^2 \theta + \sin^2\theta = 1.$$

Exercise: Write a Markdown cell that gives a definition for prime-like numbers, as described on the Project 1 webpage. The \equiv command in LaTeX can be used to produce the triple-equal symbol "$\equiv$", and the \pmod{n} command can be used to add $(\text{mod}\,\, n)$.

$\geq$ gives $\geq$

$\leq$ gives $\leq$

References to pieces of Python code¶

In Markdown, we can use backticks ` (found on the same key as tilde ~, above TAB) to render text with a uniform-width font and a gray highlight. This should always be done when referring to explicit pieces of Python code (e.g. variable names, function names, etc.).

For example, the Markdown `is_prime` will render as is_prime.

Exercise: Write a Markdown cell that explains how the is_prime function works. Use LaTeX and/or code references where appropriate in your explanation.

In [3]:
def is_prime(n):
    n_is_prime = True

    for d in range(2,n):
        if n % d == 0:
            n_is_prime = False
            break
            
    if n_is_prime:
        return True
    else:
        return False

Generally, the Markdown cell should give an intuitive explanation of the logic behind how the respective code will work. We will then combine this intuitive explanation with...

Code comments¶

To add a comment within a code cell, we simply write a hashtag # followed by whatever text we want to include. Python will ignore anything that comes after the hashtag.

In [5]:
cubes = [] # Define an empty list that will store cubes

for i in range(1,41): # Iterate through the first 40 positive integers
    cubes.append(i**3) # Add the cube of each integer to the cubes list

print(cubes)
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000, 9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000, 29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000]
In [ ]:
cubes = []               # Define an empty list that will store cubes

for i in range(1,41):    # Iterate through the first 40 positive integers
    cubes.append(i**3)   # Add the cube of each integer to the cubes list

print(cubes)

Generally, each comment should be descriptive but concise. They should serve as a translation from Python code itself to the idea behind the code, not just a restatement of what the code literally does. Typically, we want our code comments to connect to our intuitive explanation given in Markdown. It is also helpful to vertically align code comments to aid with readability.

For example, consider the following code cell and included (bad) comments:

In [7]:
div = 4 # Set div=4
N = 1000 # Set N=100

cubes = [] # Set cubes=[]
for i in range(1,N+1): # for i in range 1 to N+1
    cubes.append(i**3) # Append i**3

str_template = '{} of the first {} cubes have remainder {} after division by {}.'
for rem in range(div): # for rem in range(div)
    cubes_with_remainder = [] # Set cubes_with_remainder=[]
    for cube in cubes: # for cube in cubes
        if (cube % div == rem): # if cube % div = rem
            cubes_with_remainder.append(cube) # Append cube
    num_cubes_with_remainder = len(cubes_with_remainder)
    print(str_template.format(num_cubes_with_remainder,N,rem,div))
500 of the first 1000 cubes have remainder 0 after division by 4.
250 of the first 1000 cubes have remainder 1 after division by 4.
0 of the first 1000 cubes have remainder 2 after division by 4.
250 of the first 1000 cubes have remainder 3 after division by 4.

Let's try to rewrite the code comments to be more helpful and more readable.

In [8]:
div = 4                                        # Set the divisor to 4
N = 1000                                       # Set dividend 1000

cubes = []                                     # Initialize an empty list that will store cubes
for i in range(1,N+1):                         # Iterate through integers 1 to N
    cubes.append(i**3)                         # and append the cube of the integer

str_template = '{} of the first {} cubes have remainder {} after division by {}.'
for rem in range(div):                                   # For every possible remainder
    cubes_with_remainder = []                            # Initialize empty list of cubes that will
                                                         # have the desired remainder after division by div
    for cube in cubes:
        if (cube % div == rem):                          # If cube has the desired remainder after
            cubes_with_remainder.append(cube)            # division, then append cube
    num_cubes_with_remainder = len(cubes_with_remainder) # Count the number of cubes with
                                                         # the desired remainder
    print(str_template.format(num_cubes_with_remainder,N,rem,div))
500 of the first 1000 cubes have remainder 0 after division by 4.
250 of the first 1000 cubes have remainder 1 after division by 4.
0 of the first 1000 cubes have remainder 2 after division by 4.
250 of the first 1000 cubes have remainder 3 after division by 4.

Exercise: Add code comments to the is_prime function to explain how the function works. You may want to copy your Markdown explanation above the code cell for reference.

In [ ]:
def is_prime(n):
    n_is_prime = True

    for d in range(2,n):
        if n % d == 0:
            n_is_prime = False
            break
            
    if n_is_prime:
        return True
    else:
        return False

In-class exercise: Submit a notebook with your markdown explanation for the is_prime function and your commented code cell.