0

The following program finds the smallest integral divisor (greater than 1) of a given number n. It does this in a straightforward way, by testing n for divisibility by successive integers starting with 2.

(define (smallest-divisor n)
  (find-divisor n 2))
(define (find-divisor n test-divisor)
  (cond ((> (square test-divisor) n) n)
        ((divides? test-divisor n) test-divisor)
        (else (find-divisor n (+ test-divisor 1)))))
(define (divides? a b)
  (= (remainder b a) 0))

We can test whether a number is prime as follows: n is prime if and only if n is its own smallest divisor.

(define (prime? n)
  (= n (smallest-divisor n)))

The end test for find-divisor is based on the fact that if n is not prime it must have a divisor less than or equal to n.44 This means that the algorithm need only test divisors between 1 and n. Consequently, the number of steps required to identify n as prime will have order of growth (n).

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Martin
  • 9
  • 1

1 Answers1

3

Your last paragraph was copied with some errors. It's sqrt(n), not n, which is obvious from reading the code.

To understand this code, you need to read it, slowly. The authors of the book wrote their code in this verbose manner specifically so that it can be read, slowly, in English, and understood as it is being read. That was their goal as far as I understand it.

Like so:

(define (smallest-divisor n)
  (find-divisor n 2))

We define smallest divisor of a number n to be the result of finding a divisor of n with a starting value of 2. So we won't consider 1 as a number's divisor. So far so good.

(define (find-divisor n test-divisor)

Finding a divisor of a number n with a starting value of test divisor is done by (well, we know we start with 2; since it's an argument, this code is prepared to work with any value given to it... what are these values? for now we know that 2 is one possibility; let's hold this thought and re-examine it later):

  (cond ((> (square test-divisor) n) n)
  1. First comparing the square of the test divisor with n, and in case the square is greater than n, return n as the result. We've found it!

        ((divides? test-divisor n) test-divisor)
    
  2. If the previous test was unsuccessful, we next try testing whether test divisor divides n. If it does, we return the test divisor as the result. We've found it!

        (else (find-divisor n (+ test-divisor 1)))))
    
  3. If all the previous tests failed, we come to the crux of the matter:

    • finding a divisor of a number n with a value of test divisor that didn't pan out is the same as finding a divisor of a number n with a starting value of this test divisor value plus 1 !


    This just means in plain English, "let's try dividing n with the next testing number".

(.... so, what values are possible for test divisor to have, except 2?)

(define (divides? a b)
  (= (remainder b a) 0))

can you finish it up now?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • The function (find-divisor n test-divisor) is tail-recursive. This means, the algorithm is iterative. That is an improvement over an recursive algorthm. – Georg Fuss Dec 16 '17 at 19:59