Lecture 6

Today:

  • Checking for primeness efficiently
  • Euclid's algorithm

Checking for primes efficiently

Recall our code from before for checking primeness. We were checking to see if any of the numbers before n was a divisor of n.

In [1]:
def isprime(n):
    if n <= 1:
        return False
    d = 2
    while d<n:
        if n % d  == 0:
            return False
        d += 1
    return True

Can we make this more efficient? Yes, we don't need to check all the way up to n-1, we could actually check up to $\sqrt{n}$ because if there is a factor larger than $\sqrt{n}$, then there is also a factor smaller than $\sqrt{n}$, namely $\frac{n}{\sqrt{n}}$.

But instead of checking to see if d <= math.sqrt(n), we could check d*d <= n (taking square of a number is much quicker than taking square root)

In [2]:
def isprime(n):
    if n <= 1:
        return False
    d = 2
    while d*d<=n:    # so clever!!!
        if n % d  == 0:
            return False
        d += 1
    return True
In [9]:
print(isprime(17), isprime(18), isprime(16))
True False False


Euclid's algorithm

Let us first remember what the greatest common divisor (GCD) of two numbers is. Officially, it is the greatest number that divides both $a$ and $b$.

For example, if $a = 60$ and $b = 42$, the GCD is $6$.

$\operatorname{gcd}(a,b)$ can be defined equivalently in two other ways:

  1. If $a$ and $b$ have prime factorizations, $a = \prod_i p_i^{\alpha_i}$, and $b = \prod_i p_i^{\beta_i}$, then
$$\operatorname{gcd}(a,b) = \prod_i p_i^{\operatorname{min}(\alpha_i, \beta_i)}$$
  1. $\operatorname{gcd}(a,b)$ is the smallest positive number $d>0$ that is a linear combination:
$$ ma + nb = d $$

where $m,n \in \mathbb{Z}$ are integers.

(meaning there is a proof that shows the above characterizations are equal to the GCD)


We would like to find an algorithm that takes two nubers and gives the GCD, then code it.

Euclid's idea: assume a>b. If we want to find gcd(a,b), divide a by b,

$$a = qb + r$$

Where $r$ is the unique remainder

$$ 0 \leq r < b$$

Then: gcd(a,b) = gcd(b,r), unless $r=0$, in which case the GCD would be b. We can then repeat the same for gcd(b,r).

$$b = q_2 r + r_2 $$

so gcd(r,r_2), then repeat the same process for r and r_2.

For example: a = 60, b = 42

60 = 42*1 + 18

so gcd(60,42) = gcd(42,18)

42 = 18*2 + 6

so gcd(60,42) = gcd(42,18) = gcd(18,6)

18 = 6*3 + 0

so gcd(60,42) = gcd(42,18) = gcd(18,6) = 6

Euclid's algorithm in pseudo-code

Pseudo-code, informal description of our algorithm:

"<-" means we are setting the variable

Input: a,b positive integers<br>
Ouput: gcd(a,b), the greatest common divisor
Algorithm:
If b>a, swap a and b    
while b is not 0 do
    r <- a % b, the remainder of a divided by b
    a <- b
    b <- r
a is the GCD.

The code

In [10]:
def gcd(a,b):
    if b>a:
        dum = a
        a = b
        b = dum
    while b != 0:
        r = a % b
        a = b
        b = r
    return a
In [11]:
gcd(60,42)
Out[11]:
6
In [12]:
gcd(17,112341)
Out[12]:
1

Good exercises:

  • Close this notebook and re-implement Euclid's algorithm from scratch. Start with the basic idea that gcd(a,b) = gcd(b,r) where a=bq+r.