/// <summary> /// Debugs the IsComplete function, which /// checks whether a given string of operators /// and operands can be computed. /// </summary> public static void DebugIsComplete() { Console.WriteLine("Debugging IsComplete method:"); string func = "ln 2"; bool testComplete = DerivativeCalculator.IsComplete(func); Console.WriteLine(testComplete); }
/// <summary> /// Calculates the limit as it approaches the value from both /// the left and right and averages between the two answers /// until either the x values get too close or the threshold /// is reached. /// </summary> /// <param name="func"></param> /// <param name="limit"></param> /// <returns></returns> public static double EvaluateLimit(string func, double limit) { //Constants const double thresh = 1e-3; const double thresh_x = 1e-5; const double delta = 1e-4; //Initial step to initialize everything double x_l = limit - 1; double x_r = limit + 1; double left_ans = Calculator.Calculate(func, x_l); double right_ans = Calculator.Calculate(func, x_r); double del = Math.Abs(right_ans - left_ans); double del_x = Math.Abs(x_l - x_r); double ans = (left_ans + right_ans) / 2; //Infinite limits if (double.IsInfinity(limit)) { //Deal with undefined fractions e.g. 1/inf with L'Hopital if (double.IsNaN(ans)) { //Get index of first outer division symbol int index = StringFunctions.FindOuterSlash(func); //Split into numerator and denominator string num = func.Substring(0, index); string den = func.Substring(index + 1, func.Length - 2); //Take the derivate of the numerator and denominator string numDer = DerivativeCalculator.Derivative(num); string denDer = DerivativeCalculator.Derivative(den); string tot = numDer + "/" + denDer; return(EvaluateLimit(tot, limit)); } else { return(ans); } } //Loop until confident limit either converges or DNC while (true) { //If x values too close and still not converged, limit DNC if ((del < thresh) & (del_x < thresh)) { return(ans); } if (del_x < thresh_x) { return(double.PositiveInfinity); } //Step to next values x_l += delta; x_r -= delta; //Calculate function at current step left_ans = Calculator.Calculate(func, x_l); right_ans = Calculator.Calculate(func, x_r); //Get differences for break conditions del = Math.Abs(right_ans - left_ans); del_x = Math.Abs(x_l - x_r); //Take average of two as current solution ans = (left_ans + right_ans) / 2; //Console.WriteLine(x_l + " " + x_r + " " + del_x + " " + left_ans + " " + right_ans + " " + del + " " + ans); } }
/// <summary> /// Debugs the derivative function, checking /// against solutions found from wolframalpha.com /// in order to compute L'Hopital's rule for /// taking limits that result in an indeterminate /// form. /// </summary> public static void DebugDerivative() { Console.WriteLine("Debugging derivative methods:"); //Functions to test derivative of string[] funcList = { "(x+1)^(x+1)", "(x+2)^2", "x^5", "2^(x+2)", "x+x+x-x", "ln(1/x)", "(x+2)/(x-5)", "(x*2)+(x/5)", "2+(x+2)^2+2^x", "e^x", "cos(2)", "cos(x)", "cos(x^2)", "x", "-x", "-2^x", "sin(5)", "sin(x)", "sin(x^2)", "tan(5)", "tan(x)", "tan(x^2)", "log5(5)", "log5(x)", "log5(x^2)", "arccos(5)", "arccos(x)", "arccos(x^2)", //Everything on and below this was done with x = 0.5 "arctan(5)", "arctan(x)", "arctan(x^2)", "arcsin(5)", "arcsin(x)", "arcsin(x^2)", "sec(5)", "sec(x)", "sec(x^2)", "csc(5)", "csc(x)", "csc(x^2)", "cot(5)", "cot(x)", "cot(x^2)", "sqrt(5)", "sqrt(x)", "sqrt(x^2)", "abs(5)", "abs(x)", "abs(cos(x))", }; //From wolframalpha string[] correctAns = { "56.6625", "8", "80", "11.09035", "2", "-0.5", "-7/9", "2.2", "10.7726", "7.38905", "0", "-0.90929", "3.0272", "1", "-1", "-2.77258", "0", "-0.416146", "-2.614574", "0", "5.774399", "9.36220048", "0", "0.310667", "0.621334", "0", "-1.1547", "-1.0328", //Everything on and below this was done with x = 0.5 "0", "0.8", "0.941176", "0", "1.1547", "1.0328", "0", "0.622508", "0.263535", "0", "-3.81809", "-15.8296", "0", "-4.35069", "-16.3375", "0", "0.707107", "1", "0", "1", "-0.479426", }; //Run through test suite for (int i = 0; i < funcList.Length; i++) { //Attempt to calculate derivative, throw error if fails try { string func = funcList[i]; string ans = correctAns[i]; //Remove any whitespace for parsing //func = "log_5(x)"; //Calculate limits and output answer //double test = LimitCalc.EvaluateLimit(func, 2); //Console.WriteLine("Limit as x->" + 2 + " of " + func + " = " + Math.Round(test, 3) + " ans: " + ans); //Replace constants, convert to postfix, take derivative string analytic_func = StringFunctions.ReplaceConstants(func, 0, false); string funcPostFix = Calculator.Convert2Postfix(analytic_func); string test = DerivativeCalculator.Derivative(funcPostFix); //Choose what value to evaluate at based on function domain int index = Array.IndexOf(funcList, "arccos(5)"); if (i < index) { Console.WriteLine(func + ": " + Calculator.Calculate(test, 2) + " ans: " + ans); } else { Console.WriteLine(func + ": " + Calculator.Calculate(test, 0.5) + " ans: " + ans); } } catch { string func = funcList[i]; Console.WriteLine("Error with derivative of: " + func); } } }