/* * SumUp : Sum up (part of) the geometric series based on p/q. * Ensure that q > p > 0. * Compute (p/q)^0 + (p/q)^1 + (p/q)^2 + ... * * Print number out with '?' in place of remaining digits * we know have not converged yet. * * Parke Godfrey * 2009 October 27 * (First implemented last year.) */ import java.io.PrintStream; import java.util.Scanner; public class SumUp { public static void main(String[] args) { Scanner input = new Scanner(System.in); PrintStream output = System.out; final int LOOP_LIM = 30; final double EPSILON = 0.000001; // To collect the sum. First term, 1, included. double sum = 1.; // Read in a numerator (> 0) from the user. // Loop until the user gets it right. // No comments first time through. boolean first = true; long numerator = 0; do { if (!first) { if (numerator <= 0) { output.println( "Numerator should be positive."); } } first = false; output.print("Enter the numerator: "); numerator = input.nextLong(); } while (numerator <= 0); // Read in a denominator (> 0) from the user. // Also insist that denominator > numerator. // Loop until the user gets it right. first = true; // No corrections to user first time through. long denominator = 0; do { if (!first) { if (denominator <= 0) { output.println( "Denominator should be positive."); } else // if (denominator <= numerator) { output.print("Denominator should larger "); output.println("than numerator."); } } first = false; output.print("Enter the denominator: "); denominator = input.nextLong(); } while ((denominator <= 0) || (denominator <= numerator)); double base = (double) numerator / denominator; double term = base; // Sum up while next term is larger than epsilon, // AND we are fewer than, or equal to, allowed #steps. int steps = LOOP_LIM; while ((EPSILON < term) && (steps > 0)) { sum += term; term *= base; steps--; } // Figure out size of last term (not added). // String remS = (new Double(remD)).toString(); String remS = String.format("%.5f", term); // String sumS = (new Double(sum)).toString(); String sumS = String.format("%.5f", sum); // Confirm that doubles in Strings look like // we think they do. output.println("Remnant: " + remS); output.println("Sum: " + sumS); assert(remS.matches("^\\d*\\.\\d+$")); assert(sumS.matches("^[0-9]*\\.[0-9]+$")); // Align the decimal points between them. int rDot = remS.indexOf("."); int sDot = sumS.indexOf("."); int r = 0; int s = sDot - rDot; // Read in the prefix of sumS that we are sure of // into the answer string. String answer = sumS.substring(0, s); // Shift all digits of sumS corresponding to '0' in remS // onto the answer string. while ((s < sumS.length()) && (r < remS.length()) && ((remS.charAt(r) == '0') || (remS.charAt(r) == '.') ) ) { answer += sumS.substring(s, s + 1); r++; s++; } // Write '?' for the remaining digits. for (; s < sumS.length(); s++) { if (sumS.charAt(s) == '.') { answer += "."; } else { answer += "?"; } } // Print the resulting sum. output.println(answer); } }