javaloopswhile-loop

Is this an effective while loop?


Here is an assignment:

"Let's say you are given a number, a, and you want to find its square root. One way to do that is to start with a very rough guess about the answer, x0, and then improve the guess using the following formula x1 = (x0 + a/x0)/2

For example, if we want to find the square root of 9, and we start with x0 = 6, then x1 = (6 + 9/6)/2 = 15/4 = 3.75, which is closer. We can repeat the procedure, using x1 to calculate x2, and so on. In this case, x2 = 3.075 and x3 = 3.00091. So that is converging very quickly on the right answer(which is 3).

Write a method called squareRoot that takes a double as a parameter and that returns an approximation of the square root of the parameter, using this technique. You may not use Math.sqrt.

As your initial guess, you should use a/2. Your method should iterate until it gets two consecutive estimates that differ by less than 0.0001; in other words, until the absolute value is less than 0.0001. You can use Math.abs to calculate the absolute value."

This is exercise meant to practice while loop. As you see I did the assignment, I think it works ? But I am not sure how did I come to solution ? In other words, what should I improve here ? Is there any other way to enter the loop differently ? How to name variables more appropriately ? And lastly, is my approach good or bad here ?

public class squareRoot {
    public static void main(String args[]){
        System.out.println(squareRoot(192.0));
    }

    public static double squareRoot(double a){

        double gs = a/2; //guess
        double ig = (gs + (a/gs))/2; //improving guess

        double ig1 = (ig + (a/ig))/2; //one more improving guess, ig1

        while (Math.abs((ig-ig1)) > 0.0001){  //with ig and ig1, I am entering the loop
            ig = (ig1 + (a/ig1))/2;
            ig1 = (ig + (a/ig))/2;  //ig1 has to be less then ig
        }
        return ig1;
    }
}

Solution

  • Your approach is nearly correct.

    Let's talk about variables first. IMO, you should use full names for variables instead of acronyms. Use guess instead of gs. Use improvedGuess instead of ig etc.

    Now that's out of the way we can see where your problem lies. For the while loop to finish, two consecutive guesses' difference must be less than 0.0001. However, here you are only comparing the 1st and 2nd guesses, the 3rd and 4th guesses, the 5th and 6th guesses etc. What if the 4th and 5th guesses' difference is less than 0.0001? Your loop won't stop. Instead, it returns the value of the 6th guess. Although it is more accurate, it does not fulfill the requirement.

    Here's what I've come up with

    public static double squareRoot(double a){
    
        double guess = a/2;
        double improvedGuess = (guess + (a/guess))/2;
    
        while (Math.abs((guess - improvedGuess)) > 0.0001){
            guess = improvedGuess;
            improvedGuess = (guess + (a/guess))/2;
        }
        return improvedGuess;
    }