TT1–TT3 - Programs and prime factorisation

TT1–TT3 - Programs and prime factorisation

Write, trace and refine short number-theory programs. Use conditions, loops, functions, local and global variables, input and output; build a reliable prime test and use unique prime factorisation.

Tell the program what counts

A program announces that 11 is prime. Has the computer discovered new mathematics, or have we missed a condition?

The computer has followed its instructions. To make a useful mathematical program, specify the domain, the test and what the output means.

You already know

A prime is an integer greater than 11 with exactly two positive divisors. Divisibility means an integer remainder of zero. Earlier mathematics used algorithms; here we write their steps explicitly in Python.

The name on the left of = stores a value. input() reads text, so int() converts integer text into an integer value. print() displays a result. An if condition chooses a branch; indentation identifies the statements inside it.

Conditions and integer arithmetic

In Python, n % d is the remainder when integer n is divided by positive integer d. Use == to test equality, rather than the assignment symbol =. The condition n % d == 0 tests whether d divides n.

Start with a domain check. Passing it makes a number a candidate for testing, not a proved prime.

Worked example 1: a number inside the domain

Question. Trace this program for input 15.

Python
n = int(input("Integer n: "))
if n < 2:
    print("Not prime")
else:
    print("Candidate for a prime test")

Plan. Convert the input, evaluate the comparison, then follow exactly one branch.

StepResultReason
Convert inputn = 15Store an integer.
Test n < 2False15>215>2.
Follow elseCandidate for a prime testThe domain check passed.

Why this step? “Candidate” does not assert primality: 1515 still needs a divisor test.

Answer. The output is Candidate for a prime test.

Check. 15=3×515=3\times5, so calling it prime here would be wrong.

Change only the input to 1. The same comparison must select the other branch.

Worked example 2: excluding one

Question. Trace the same program for input 1.

Python
n = int(input("Integer n: "))
if n < 2:
    print("Not prime")
else:
    print("Candidate for a prime test")

Plan. Repeat the conversion and condition check.

StepResult
Convert inputn = 1
Test n < 2True
Execute first branchNot prime

Why this step? The definition's “greater than 11” requirement must be encoded; a later divisor loop may have no iterations for 11.

Answer. The output is Not prime.

Check. Zero and negative integers take this branch too. Non-integer text is outside this short program's input contract.

Programming syntax is not supplied in the formula booklet. The mathematical definition determines the correct condition.

Watch out

Wrong: treat any positive integer as a possible prime. Right: exclude integers below 22, and reserve a prime verdict until the divisor test succeeds.

Write a domain check with new messages.

Check a whole range

A loop repeats a test for successive candidates. An accumulator remembers a running count or total.

In Python, range(1, n + 1) supplies integers 11 through nn. Its stopping value is excluded, which is why the + 1 matters. Initialise the accumulator before the loop; update it only when the condition holds.

Worked example 3: counting divisors

Question. Determine the output for n = 12.

Python
n = 12
count = 0
for d in range(1, n + 1):
    if n % d == 0:
        count = count + 1
print(count)

Plan. List candidates satisfying the condition and count the updates.

Successful d11223344661212
Updated count112233445566

Why this step? The loop visits every candidate, but the counter changes only at actual divisors.

Answer. The output is 6.

Check. The factor pairs (1,12),(2,6),(3,4)(1,12),(2,6),(3,4) account for all six divisors.

Change only n to 13. The endpoint is now a prime.

Worked example 4: two successful tests

Question. Trace this divisor count.

Python
n = 13
count = 0
for d in range(1, n + 1):
    if n % d == 0:
        count = count + 1
print(count)

Plan. Find successful candidates, keeping the upper endpoint.

Successful d111313
Updated count1122

Why this step? range(1, n) would miss nn itself and report only one divisor of a prime.

Answer. The program displays 2.

Check. Candidates 22 through 1212 all leave non-zero remainders.

Changing an update from count + 1 to total + d changes counting divisors into adding them.

Watch out

Wrong: reset the accumulator inside the loop. Right: initialise it once before the loop so earlier successes are remembered.

Use a sum in place of a count.

Keep each calculation's variables local

A function packages an algorithm for calls with different arguments. return passes a value back to its caller; it differs from displaying a value with print.

Local and global variables

A variable assigned inside a function, including a parameter, is local unless explicitly declared otherwise. A variable assigned at the outer program level is global. The same spelling can name different variables in different scopes.

Each call below gets a fresh local counter. Its parameter receives the argument's value without overwriting a global variable.

Worked example 5: a local counter

Question. Determine all three printed lines.

Python
def divisor_count(n):
    count = 0
    for d in range(1, n + 1):
        if n % d == 0:
            count += 1
    return count

n = 12
count = 100
result = divisor_count(10)
print(result)
print(n)
print(count)

Plan. Trace local variables, then return to the unchanged outer variables.

StageLocal stateOuter state
Enter functionn = 10, count = 0n = 12, count = 100
Find divisors 1,2,5,101,2,5,10count = 4Unchanged
ReturnPass 44 to callerresult = 4

Why this step? The local count is distinct from the global count.

Answer. The lines are 4, 12, 100.

Check. The local parameter was 1010; no assignment changed the global n.

Change only the call's argument from 10 to 13.

Worked example 6: fresh state for another call

Question. Determine this program's output.

Python
def divisor_count(n):
    count = 0
    for d in range(1, n + 1):
        if n % d == 0:
            count += 1
    return count

n = 12
count = 100
result = divisor_count(13)
print(result)
print(n)
print(count)

Plan. Count the argument's divisors, then inspect the globals separately.

QuantityValue
Local parameter1313
Local counter returned22
Global n1212
Global count100100

Why this step? A new call starts its own counter at zero, not at the preceding call's final count.

Answer. The lines are 2, 12, 100.

Check. 1313 has two positive divisors; both outer assignments remain unchanged.

A function can read an unshadowed global name. A global declaration can make an assignment affect that outer name, but none is needed here. Passing inputs and returning results makes a mathematical calculation's dependencies explicit and easier to test.

Watch out

Wrong: expect a local assignment to update a same-named global. Right: distinguish the scopes and use the returned result.

Trace the same boundary with new data.

A return belongs in the right place

One divisor proves a number composite. One non-divisor does not prove it prime: every required candidate must first be eliminated.

This basic routine accepts integers. For n≥2n\ge2, it tests proper divisor candidates 22 through n−1n-1.

Python
def is_prime(n):
    if n < 2:
        return False
    for d in range(2, n):
        if n % d == 0:
            return False
    return True

The final return True is outside the loop. For n=2n=2, the loop is empty: the domain check and absence of possible proper divisors make True correct.

Worked example 7: exhaust the candidates

Question. Trace is_prime(7) using this routine.

Plan. Pass the guard and inspect every required candidate before accepting.

d2233445566
7 % d1111332211

The loop ends without a zero remainder; the function then returns True.

Why this step? Accepting after the first non-divisor would wrongly accept some composite numbers.

Answer. True, after five remainder tests.

Check. 77 has only the positive divisors 11 and 77.

Change only the argument to the square 99.

Worked example 8: stop at a divisor

Question. Trace is_prime(9).

Plan. Stop at the first zero remainder.

dRemainderAction
2211Continue
3300Return False

Why this step? return exits the whole function; candidates 44 through 88 are never tested.

Answer. False, after two remainder tests.

Check. 9=329=3^2: a square-root divisor must be included.

Predict all four lines, run the program, then replace 29 by 49 in the list. Predict the changed line before running again.

Continue this lesson.

You’re previewing NovaLearn without an account. Create a free account to read the rest.

Create free account