CMPSCI 250 Discussion #5: Infinitely Many Primes

David Mix Barrington

6/8 March 2006

The questions were steps toward proving correctness of the following pseudo-Java method (similar to that on page 4-12 of the text):


       void factor (natural n)
       {// Prints the sequence of prime factors of n to System.out, one per line
        // Special cases: outputs empty sequence if n is 0 or 1
           if (n <= 1) return;
           natural d = 2;
           while ((n % d) != 0) && (d < n)) {
              if (d*d > n) d = n;
              else d++;}
           System.out.println (d);
           factor (n/d);}
  1. What is the output of factor on input n = 60?

    
             2
             2
             3
             5
    
  2. Explain the purpose of the if statement in the while loop.

    The goal of the entire loop is to increase d until it is the smallest prime factor of n. If d*d is greater than n, it must be that every number in the range from 2 through √n has been tested as a possible divisor of n and been found not to be such a divisor. So n must be a prime number, and is its own least prime divisor. We set d to n and skip the other values of d between √n and n, saving time.

  3. Why does factor only output prime numbers? (Hint: Suppose that x % d is 0 and d has a divisor e with e > 1. What is x % e?)

    Note that the output is always the natural d, and is always output immediately after the while loop terminates. By the condition of the while loop, this can only happen when d divides n and/or is equal to n. If d is equal to n when the loop ends, n (and therefore d) must be prime, because d has passed through every value from 2 thorugh √n and failed to divide n each time. (Note that if the if clause is ever executed, n must be prime.) If d is some other number, we show that it cannot have a proper divisor e with 1 < e < d. Suppose, to get a contradiction, that it does. This e must have been a value of d at some point, because the if clause has never been executed and so d has gone by ones from 2 to its current value. But (following the hint) e must divide n because e divides d and d divides n. So we would have dropped out of the while loop at that point, but we didn't, so there is a contradiction. Since d cannot be composite, and must be at least 2 (since it changes only by either increasing by one or by being set to n, which by this point is at least 2), it is prime.

  4. Why do the numbers output by factor(x) multiply together to give x?

    Here we assume that the recursive call in factor(x), to factor(x/d), causes the correct behavior according to factor's specification. So it outputs a series of zero or more naturals, one per line, that multiply to x/d. The output of factor(x) is the final value of d, followed by these numbers, so the product of the numbers output is d*(x/d).

    In general with Java integer division (the "/" operator), the identity x = y*(x/y) is not true. But it is true when y divides x evenly. Here we know that d divides n evenly because of the while loop, which can only terminate with d dividing n or d ≥ n (where d > n can never happen because d only changes by being increased by one or set to n).

  5. Why does the procedure terminate at all? (Hint: Why could we guarantee that the Euclidean Algorithm always terminates.)

    First, we should make sure that the loop cannot go on forever. When the loop starts, d is 2 and n is at least 2. Then d is either increased by 1 or set to n, until it divides n or equals n. Even if it is never a proper divisor of n, it will eventually reach n and the loop will end.

    One of the versions of the fifth Peano Axiom in Section 4.1 says that a recursive algorithm, which only calls itself on x-1 when running on x, must terminate. This is actually a different situation because the argument is not necessarily decreasing by 1 each time. But it is getting smaller each time, because d is always at least 2 and we replace n by n/d. A sequence of naturals that gets smaller at each step must eventually reach 0, and when the method is called on an argument of 0 it terminates without recursion. Later we will use Strong Induction to prove termination of this method more formally.

Last modified 8 March 2006