This time, one of my labs state that I need to write a complete java program which will calculate the square root of a number via Newton's method. The reason behind using Newton's method, as opposed to Math.sqrt(x)
is so that I get to practice the use of simple IO, conditional expressions, loops, and nested loops.
The complete set of instructions are as follows:
Assume you want to compute the square root of x.
First: We always start with a guess/approximation that the square root of any value for x is y = 1.0
Next we compute the average of this y value plus the x value divided by the y value.
This equation → ( y + (x/y) ) / 2.
The result from solving this equation then becomes the new approximation of the square root (the new y value). This new y value will be closer to the actual value for the square root of x than the original y guess of 1.0
Repeat the step above using each new computed value for y as the new guess for the square root of x until the y value is close enough.
For example: suppose we want to compute the square root of 2 then the computation would proceed as follows (all values as double): x = 2.0 and y = 1.0
Iteration Guess Quotient Average
Number for y x/y ( y + (x/y) ) / 2
1 1.0 2.0/1.0 => 2.0 (1.0 + 2.0/1.0)/2.0 => 1.5
2 1.5 2.0/1.5 => 1.33333 (1.5 + 1.33333)/2.0 => 1.41666
3 1.41666 2.0/1.41666 => 1.41176 (1.41666 + 1.41176)/2.0 => 1.41421
4 1.41421 etc...
The solution is achieved when the square of the guess is “same” as the value of x (the definition of square root). Unfortunately, for most numbers the exact solution can never be reached this way so the process continues forever. In order to ensure that the computation process actually stops we must change the stop condition of the loop to be “close enough”. Close enough is the tolerance (a small number) which we accept as being a good approximation of the exact value.
Close enough occurs when the absolute difference between x and (y*y) is less than the tolerance (defined by the user).
In order to see how your program is progressing print out the iteration number and the guess value. Use at least 8 digits after the decimal value and 2 before the decimal. In the example run shown below only 5 digits after the decimal are used.
Example Run:
Square Root approximation program
Enter the value : 2.0
Enter the tolerance : 0.00001
Iteration Guess Guess Absolute value
Number value Squared Difference
1 1.00000 1.00000 1.00000
2 1.50000 2.25000 0.25000
3 1.41666 2.00693 0.00693
4 1.41421 1.99999 0.00001
Approximated Square root of 2.0 = 1.41422
The resulting code that I wrote to solve this problem is as follows:
import java.util.Scanner;
/**
* SRN: 507-147-9
*/
public class Lab8_1 {
public static void main(String[] args) {
// new input
Scanner input = new Scanner(System.in);
// define vars
int iteration = 1;
double x, y, guessSquared = 1, quotient, average, tolerance, absValDiff = 1;
y = 1.0;
// program name
System.out.println("Square Root approximation program");
System.out.println();
// prompt variables
System.out.print("Enter the value : "); // prompt x value
x = input.nextDouble(); // store input as "x"
System.out.print("Enter the tolerance : "); // prompt tolerance
tolerance = input.nextDouble(); // store input as "tolerance"
System.out.println();
// print formatted header
System.out.println("Iteration Guess Guess Absolute value");
System.out.println("Number value Squared Difference");
System.out.println();
// print first calculation
System.out.printf("%9d %11.8f %11.8f %11.8f \n", iteration, y, guessSquared, absValDiff);
// increment the value of "iteration" by 1
iteration++;
while (absValDiff > tolerance) {
// looped calculations
quotient = x / y;
average = (y + quotient) / 2;
y = average;
guessSquared = y * y;
absValDiff = Math.abs(x - guessSquared);
// print results per iteration
System.out.printf("%9d %11.8f %11.8f %11.8f \n", iteration, y, guessSquared, absValDiff);
// increment the value of "iteration" by 1
iteration++;
}
// print results
System.out.println();
System.out.printf("Approximated Square root of " + x + " = %11.8f \n", y);
}
}
With this, I do have a question regarding the accuracy of my responses as opposed to the ones in the example. Even though mathematically, the correct floating point numbers are stored in my variables, when the results are printed to the console, the last digit of my floating point is always rounded up. From my perspective, this feels similar to the round-off errors one would get on a calculator, where the result of the calculations performed are only approximate representations of the actual numbers, since only fixed point rational numbers can be represented exactly within the machine.
An example of this kind of error would be: 2/3 = 0.666666667
Is there a way that I could capture a set length for my variables using the printf
format without allowing the number to be round up when it is printed to the console?
printf()
rounds to the closest number, up or down. And2/3 = 0.666666667
is in fact a better approximation for the infinite digits series of0.666666...
than2/3 = 0.666666666
. So, it's not an error, but the best possibility, and I wouldn't change that behaviour. \$\endgroup\$