import SimpleOutput;

/**
 * The square root algorithm from homework 3.  Run the program
 * with val and accuracy on the command line and it prints out
 * the result.  For example,
 *
 *   java SquareRoot 2 100
 *     computes the square root of 2 to two decimal places
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of March 2000
 */
public class SquareRoot
{
  // +------+----------------------------------------------------
  // | Main |
  // +------+

  public static void main(String[] args) {
    double val = 0;
    long n = 0;
    double root;
    SimpleOutput out = new SimpleOutput();   
    // Sanity check.
    if (args.length != 2) {
      out.println("Usage: java SquareRoot value n");
      System.exit(1);
    }
    // Get the value.
    try { val = (new Double(args[0])).doubleValue(); }
    catch (NumberFormatException e) {
      out.println("The steps must be a number.");
      System.exit(2);
    } // catch
    // Get the n.
    try { n = (new Long(args[1])).longValue(); }
    catch (NumberFormatException e) {
      out.println("N must be an integer.");
      System.exit(3);
    } // catch
    // Verify that the preconditions are met.
    if (val < 0) {
      out.println("The value must be positive.");
      System.exit(4);
    } // if (val < 0)
    if (n <= 0) {
      out.println("N must be positive.");
    } // if (n <= 0)
    // Compute the square root
    root = sqrt(val,n);
    out.println("The square root of " + val + " is " + root);
    out.println("Java says that it is " + Math.sqrt(val));
  } // main(String[])

  // +---------+-------------------------------------------------
  // | Helpers |
  // +---------+

  /**
   * Compute the square root of val to accuracy 1/n.
   * Pre: (1) val >= 0
   *      (2) n > 0
   *      (3) The square root of val can be represented.
   * Post: (1) Returns a value v such that |v-sqrt(val)| < acc.
   */
  public static double sqrt(double val, long n) {
    // Compute 1/nth of the range of possible values
    double accuracy = 1.0/((double) n);
    // Start with an initial guess
    double guess = 0;
    // Determine the difference between the square of the guess
    // and the actual square root.
    double diffsquared = val;

    // Step through all the possible values between 0 and val.
    for (double nextguess = 0.0;
         nextguess <= val;
         nextguess = nextguess + accuracy) {
      // Compute the difference between the square of the guess
      // and the actual value.
      double nextdiff = Math.abs(nextguess*nextguess-val);
      // If it's better, use it.
      if (nextdiff < diffsquared) {
        guess = nextguess;
        diffsquared = nextdiff;
      }
    } // for
    return guess;
  } // sqrt(double,double)
} // class HW3

