CS3343/3341 Analysis of Algorithms Spring 2012 Weird Topic |
Newton's Method to
Perform Division |
Newton's Method is used to find successive approximations to the roots of a function. If the function is y = f(x) and x0 is close to a root, then we usually expect the formula below to give x1 as a better approximation. Then you plug the x1 back in as x0 and iterate. See Newton's Method for a derivation of the formula below.
Suppose one wants to do division, say by a number d. It suffices to calculate the reciprocal of d, that is, 1/d. In order to calculate 1/d, use the function f(x) = 1/x - d, with 1/d as its root. Using Newton's method, one gets the equations:
Newton's Method, division by the double d | Outputs (red = incorrect digits) |
---|---|
// DivD: use Newton's method for 1/d // only divisions used are by 2 public class DivD { private double mul; // denormalizing factor // normalize to 0.5 <= d <= 1 public double norm(double d) { // divide d by power of 2 mul = 1.0; // power of 2 double d0 = d; while (d0 > 1) { // divide by 2, will // later divide by 2 again d0 = d0/2.0; mul = mul*2.0; } while (d0 < 0.5) { d0 = d0*2.0; mul = mul/2.0; } // d0 now normalized return d0; } // denorm: reverse the normalization public double denorm(double invD0) { return invD0/mul; } // calculate 1/d0, 0.5 <= d0 <= 1 public double invD(double d0) { // initial approx: 48/17 - 32/17*d0 double x0 = 2.82353 - 1.88235*d0; System.out.println("1st approx to 1/d0:"+ x0); double x1; for ( ; ; ) { x1 = x0*(2 - d0*x0); System.out.println(x1); if (Math.abs(x1 - x0) < 1.0e-7) break; x0 = x1; } return x1; } public static void main(String[] args) { // calculate 1/d for any d > 0 DivD divD = new DivD(); double d = Double.parseDouble(args[0]); System.out.println("d:" + d + ", want 1/d"); // normalize to 0.5 <= d <= 1 double d0 = divD.norm(d); // d0 now normalized System.out.println("normalized, d0:" + d0 + ", want 1/d0"); double invD0 = divD.invD(d0); // denoramlize: divide invD0 by mul double invD = divD.denorm(invD0); System.out.println("1/" + d + " = \t" + invD); System.out.println("check on ans:\t" + 1.0/d); } } | d:3.141592653589792, want 1/d (d = π) normalized, d0:0.785398163397448, want 1/d0 1st approx to 1/d0:1.3451357671288138 1.2691797691683022 1.273226599977265 1.2732395446035567 1.2732395447351632 1/3.141592653589792 = 0.3183098861837908 check on ans: 0.3183098861837908 |