Additional Problems

Smallest Divisor of an integer

Problem: Given an integer m, write a program that will find its smallest exact divisor other than 1.

      Is the problem clear and well-defined?

      what is a divisor?

    For any number m, there are divisors

    There are at least two divisors

    All divisors of m can be totally ordered

    Can m be 0?

    Can it be negative?

    What if m is prime?

      Assume: m > 0

      Assert: if m is prime, return 1 else the smallest divisor other than 1

Towards a strategy

      All divisors of m are between 1 and m

      Strategy 1:

   Enumerate all divisors of m

   choose the smallest one

      Better Strategy:

   Starting from 2, check one by one whether it is a divisor of m

   If one is found before m is reached then return.

   Otherwise, return 1.

      How to check a divisor?

      Can we do better?

Towards a Better Strategy

      The above inspects (m-1) numbers, in the worst case

   for even numbers, the answer is 2

   for odd numbers, no need to check an even number

      How to check whether a number is even or not?

 

      Do we have go up to m?

The Algorithm

    Algorithm st_divisor
Input m
Assume: m > 0
Output d
Assert: if m is prime, d is 1; otherwise,

                d is the smallest divisor other than 1

1. if ( even(m)) then d = 2
   else
     1.1  d = 3
     1.2  do while ((m mod d /= 0 ) and (d < sqrt(m)))

                         1.2.1  d = d + 2
2. if (m mod d /= 0) then  d = 1

end algorithm

Observation

      How to compute Square roots?

      Better to remove the square root computation before the loop

   Look for removing computations inside loops

      Note m mod d can not be removed

      Is the algorithm correct?

      Does it terminate?

 Loop invariant

      The invariant condition is:

m is odd, d is odd, 1 < d <= sqroot(m) + 1

for no x: 1 < x < d: x is a divisor of m

 

      Bound Function:

                             (m d)

Improvements

      How many iterations?

   In the worst case, the largest integer less than or equal to sqroot(m)/2

   0, if m is even

 

      Is there a better algorithm?

   A lot of redundant checks are still made

   Look for prime divisors

The square root problem

      Problem: Write a program that computes the square root of a given number.

      Is the problem definition clear?

   If 25 is the input, then 5 is the output

   If 81 is the input, then 9 is the output

   If 42 is the input, then ?

      For non perfect squares, the square root is a real number

 

      So the output should be close to the real square root

 

      How close? to a given accuracy

A more precise specification

      Problem: Write a program that given a number m outputs a real value r s.t. r*r differs from m by a given accuracy value e

 

      More precisely, the program outputs r s.t.

                     |r*r - m| < e

Solution Strategy

Guess and Correct Strategy:

      Choose an initial guess r less than m

      If r*r > m then keep decreasing r by 1 until r*r is less than or equal to m.

      If r*r < m then keep increasing r by 0.1, until r*r exceeds or equals m

      If r*r > m then decrease r by 0.01 until r*r exceeds or equals m.

        ...

 

      Terminate the computation when  r*r equals m or differs from m by a given small number.

Idea

 

 

 

 

 

 

 

 

      Number of iteration depends upon the initial guess

      If m is 10,00,000 and the initial guess is 300 then over 700 steps are needed

      Can we have a better strategy?

Towards a better strategy

      The basic idea of the strategy is to obtain a series of guesses that

   falls on either side of the actual value

   narrows down closer and closer

      To make the guess fall on either side

   increase/decrease the guess systematically

      To narrow the guess

   the amount of increase/decrease is reduced

      Improving the strategy

   faster ways of obtaining new guess from the old one

One Strategy

      Given a guess a for square root of m

   m/a falls on the opposite side

   (a + m/a)/2, can be the next guess

      This gives rise to the following solution

   start with an arbitrary guess, r_0

   generate new guesses r_1, r_2, etc by using the averaging formula.

      When to terminate?

   when the successive guesses differ by a given small number

The algorithm

Algorithm Sq_root

 Input m, e: real

 assume: m>0, 1 > e > 0

Output r1, r2: real

 assert:: |(r2 * r2 - m) | <= |(r1 * r1 - m)|, |r1 - r2| < e 

  

 1. r1 = m/2

 2. r2 = r1

 

 3.  Do while (|r1 - r2| > e) steps 3.1 and 3.2

            3.1   r1 = r2

            3.2   r2 = (r1+m/r1)/2

 end Algorithm

 

Analysis of the algorithm

      Is it correct? Find the loop invariant and bound function

 

      Can the algorithm be improved?

 

      More general techniques available

  Numerical analysis