package rebelsky.sqrt; import java.math.BigDecimal; import java.io.PrintWriter; public class MyMath2 { public static BigDecimal sqrt(BigDecimal num, BigDecimal epsilon) throws Exception { PrintWriter pencil = new PrintWriter(System.out, true); BigDecimal approx = new BigDecimal(1); return sqrt(num, approx, epsilon, pencil); } public static BigDecimal sqrt(BigDecimal num, BigDecimal approx, BigDecimal epsilon, PrintWriter pencil) throws Exception { int scale; scale = epsilon.scale()+1; approx = approx.add(num.divide(approx, scale, BigDecimal.ROUND_HALF_UP)); approx = approx.divide(new BigDecimal(2)); // Compute the difference between a and n/a BigDecimal diff; diff = approx.subtract(num.divide(approx, scale, BigDecimal.ROUND_HALF_UP)); diff = diff.abs(); if (diff.compareTo(epsilon) <= 0) { return approx; } else { pencil.println(approx); return sqrt(num, approx, epsilon, pencil); } } } /* * Problems? * * Might give too good an approximation b/c it improves the approximation * before checking. * * Do we need a scale? * YES * * Could we just type "epsilon.scale()+1" instead? * YES, but this is clearer. * * The primary sqrt procedure should not create a pencil, it should * take it as a parameter. * * Why use new BigDecimal(1) instead of BigDecimal.ONE? * * Computing the quality of an approximation by dividing is inefficient. */