[Tutor] primality testing

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Fri May 9 16:45:02 2003


> def prime(n):
> 	for in in range(2, sqrt(n)+1):
> 		if n % i == 0:
> 			return 'Composite'
>
> 	return 'Prime'


Small typo; Dana meant to use 'i', not 'in', for the statement,

    for i in range(2, sqrt(n) + 1):






There's an alternative way of checking for primality that's very cool;
it uses randomness and number theory!  There's some code here that shows
how to do it:

    http://www-mitpress.mit.edu/sicp/chapter1/node17.html

The code in the link above is written in a language called Scheme, but
it's actually not too bad to do the conversion from Scheme to Python.
For example, if we see something like this:


;;; Scheme code
(define (expmod base exp m)
  (cond ((= exp 0) 1)
        ((even? exp)
         (remainder (square (expmod base (/ exp 2) m))
                    m))
         (else
          (remainder (* base (expmod base (- exp 1) m))
                     m))))
;;;


This code in Scheme does something akin to:

    (base ** exp) % m

It does it in a cute way so that we can avoid doing huge products --- it
applies the modulo '%' function at the same time that it's calculating the
powers, to keep the numbers small and easy to calculate.


That expmod function can be translated into Python like this:

###
def expmod(base, exp, m):
    """Calcuates base**exp modulo m."""
    if exp == 0:
        return 1
    elif is_even(exp):
        return square(expmod(base, exp / 2, m)) % m
    else:
        return (base * (expmod(base, exp-1, m))) % m
###




For those who are interested, here's the complete translation:

###
"""Primality testing using Fermat's little theorem."""

import random


def is_fast_prime(n, times):
    """Perform the fermat primality test 'times' times on the number n."""
    for i in range(times):
        if not fermat_test(n): return False
    return True


def fermat_test(n):
    """Tests to see if n is possibly prime.  It can give false
    positives, although it never gives false negatives."""
    def try_it(a):
        return expmod(a, n, n) == a
    return try_it(1 + random.randrange(n-1))


def is_even(x):
    """Returns true if x is even."""
    return x % 2 == 0


def square(x):
    """Returns the square of x."""
    return x * x


def expmod(base, exp, m):
    """Calcuates base**exp modulo m."""
    if exp == 0:
        return 1
    elif is_even(exp):
        return square(expmod(base, exp / 2, m)) % m
    else:
        return (base * (expmod(base, exp-1, m))) % m
###



Here's more information on primality tests from MathWorld:

    http://mathworld.wolfram.com/PrimalityTest.html


Hope this helps!