public static bool DoMaths(ref string number, ref double l1, ref double l2, ref Operation op, Operation newOp, ref bool firstOperation) { // Do not assign l2 if it's first time if (!firstOperation) { if (!double.TryParse(number, out l2)) { number = MUtil.ExpNotationToDecimalNotation(number); if (!double.TryParse(number, out l1)) { Debug.LogError("Cannot parse " + number + " to number ( double )"); return(false); } } l1 = op.function.Invoke(l1, l2); } else { firstOperation = false; } number = ""; op = newOp; return(true); }
public static double Calculate(string data) { if (data.Length == 0) { Debug.LogError("Data is empty"); return(double.NaN); } if (operations == null) { FillOperationsList(); } if (bracketsFunctions == null) { FillBracketsFunctions(); } data = MUtil.RemoveSpaces(data); data = ChangePunctuationMark(data); data = MUtil.ExpNotationToDecimalNotation(data); data = ReplaceConstants(data); data = CalculateBrackets(data); if (data.StartsWith("E")) { return(double.NaN); } data = CalculateExpression(data); double result = 0; if (!double.TryParse(data, out result)) { Debug.LogError("Cannot parse " + data + " to result ( double )"); return(double.NaN); } return(result); }
/// <summary> /// Gets bracket operation and creates list from them /// </summary> /// <param name="data">String with expression</param> /// <param name="bracketOperations"></param> /// <returns>Data without brackets operations</returns> private static string CalculateBrackets(string data) { string actExpr = ""; string specialMode = ""; int bracketLevel = 0; List <BracketOperation> bracketOperations = new List <BracketOperation>(); for (int i = 0; i < data.Length; i++) { if (bracketLevel > 0) { actExpr += data[i]; } if (data[i] == ')') { if (bracketLevel > 1) { bracketLevel--; } else if (bracketLevel == 1) { BracketOperation operation = new BracketOperation(actExpr.Remove(0, 1).Remove(actExpr.Length - 2, 1), i - actExpr.Length + 1 - specialMode.Length); if (specialMode.Length > 0) { Function f = FindFunction(specialMode, true); if (f == null) { Debug.LogError("Cannot find function " + specialMode); return("ENOFUNCTION"); } operation.specialFunction = f; } //Debug.Log("Bracket operation: \"" + operation.operation + "\""); //Debug.Log("Bracket operation start: " + operation.positionInString); bracketOperations.Add(operation); data = data.Remove(i - actExpr.Length + 1 - specialMode.Length, actExpr.Length + specialMode.Length); i -= actExpr.Length + specialMode.Length; actExpr = ""; specialMode = ""; bracketLevel = 0; } else { Debug.LogError("Closing bracket without opening"); return(double.NaN.ToString()); } } else if (data[i] == '(') { bracketLevel++; if (bracketLevel == 1) { actExpr += data[i]; string s = ""; for (int j = i - 1; j >= 0; j--) { if (MUtil.IsNumber(data[j])) { break; } if (FindOperation(data[j]) != null) { break; } s = "" + data[j]; specialMode = specialMode.Insert(0, s); } } } } //Debug.Log("Bracket level: " + bracketLevel); if (bracketLevel > 0) { Debug.LogError("No closing bracket"); return("ENOCLOSEBRACKET"); } // Recurently get additional brackets from brackets for (int i = 0; i < bracketOperations.Count; i++) { BracketOperation op = bracketOperations[i]; op.operation = CalculateBrackets(bracketOperations[i].operation); bracketOperations[i] = op; } // Calcualate brackets for (int i = 0; i < bracketOperations.Count; i++) { string rtBeforeComma = ""; string rtAfterComma = ""; bool rtIsAfterComma = false; string result; // Two args functions if (bracketOperations[i].specialFunction != null && bracketOperations[i].specialFunction.function == null && bracketOperations[i].specialFunction.twoArgFunction != null) { for (int j = 0; j < bracketOperations[i].operation.Length; j++) { if (bracketOperations[i].operation[j] == ';') { rtIsAfterComma = true; continue; } if (rtIsAfterComma) { rtAfterComma += bracketOperations[i].operation[j]; } else { rtBeforeComma += bracketOperations[i].operation[j]; } } rtBeforeComma = CalculateExpression(rtBeforeComma); //Debug.Log("rtBeforeComma after: " + rtBeforeComma); rtAfterComma = CalculateExpression(rtAfterComma); //Debug.Log("rtAfterComma after: " + rtAfterComma); result = "0"; } else { result = CalculateExpression(bracketOperations[i].operation); } double res; if (!double.TryParse(result, out res)) { Debug.LogError("Cannot convert " + result + " to result ( double )"); return("ECONVERSION"); } if (bracketOperations[i].specialFunction != null) { if (bracketOperations[i].specialFunction.function != null) { res = bracketOperations[i].specialFunction.function.Invoke(res); result = MUtil.ToStandardNotationString(res); if (result.Length == 0) { result = "0"; } } else { if (bracketOperations[i].specialFunction.function == null && bracketOperations[i].specialFunction.twoArgFunction != null) { if (rtBeforeComma.Length == 0 || rtAfterComma.Length == 0) { Debug.LogError("Bad 2 arg function arguments"); return("EBADROOTARG"); } else { double l1; double n; if (!double.TryParse(rtBeforeComma, out l1)) { Debug.LogError("Cannot convert first root argument to l1 ( double )"); return("EBADCONVERSION"); } if (!double.TryParse(rtAfterComma, out n)) { Debug.LogError("Cannot convert second root argument to n ( double )"); return("EBADCONVERSION"); } res = bracketOperations[i].specialFunction.twoArgFunction(l1, n); //OperationFunctions.Rt(l1, n); result = MUtil.ToStandardNotationString(res); if (result.Length == 0) { result = "0"; } } } } //Debug.Log("Result: " + result); } data = data.Insert(bracketOperations[i].positionInString, result); // Fix offsets for (int j = i + 1; j < bracketOperations.Count; j++) { BracketOperation tOp = bracketOperations[j]; tOp.positionInString += result.Length; bracketOperations[j] = tOp; } } return(data); }
public static double Power(double l1, double l2) { return(MUtil.Power(l1, l2)); }
public static string CalculateSpecificOperations(string data, Operation[] allowedOperations) { double l1 = 0, l2 = 0; Operation op = null; // First operation is always addition string actualNumber = ""; bool noPrevOperators = true; bool operationIsAllowed = false; int startIndex = 0; string startData = ""; for (int i = 0; i < data.Length; i++) { op = FindOperation(data[i]); if (op != null) { if (i == 0 && data[0] == '-') { startData += data[0]; continue; } startIndex = i; break; } startData += data[i]; } // No operator if (op == null) { return(data); } if (startIndex == 0) { Debug.LogError("Operator without number: \"" + data + "\" op: " + op.name); return("EOPWTHTNMBR"); } if (!double.TryParse(startData, out l1)) { if (startData[startData.Length - 1] == 'E') { for (int i = startData.Length; i < data.Length; i++) { if (MUtil.IsNumber(data[i]) || data[i] == '+') { startData += data[i]; } else { break; } } for (int i = 0; i < data.Length; i++) { if (data[i] == 'E') { if (data.Length > i + 1) { if (data[i + 1] == '+') { i += 2; } } } op = FindOperation(data[i]); if (op != null) { break; } } l1 = MUtil.GetDoubleFromExpNotation(startData); data = data.Remove(0, startData.Length); string decimalStartData = MUtil.ExpNotationToDecimalNotation(startData); data = data.Insert(0, decimalStartData); startData = decimalStartData; startIndex = startData.Length; Debug.Log("Data after converting exponent notation: " + data); } else { Debug.LogError("Cannot convert " + startData + " to l1 ( double )"); return("ECONVERSION"); } if (l1.Equals(double.NaN)) { Debug.LogError("Cannot convert " + startData + " to l1 ( double ). l1 = NaN"); return("ECONVERSION"); } } actualNumber = startData; bool firstOperation = true; // Multiply for (int i = startIndex; i < data.Length; i++) { Operation aop = FindOperation(data[i]); if (aop != null) { if (actualNumber.Length == 0 && data[i] == '-') { actualNumber += data[i]; continue; } operationIsAllowed = false; for (int j = 0; j < allowedOperations.Length; j++) { if (op == allowedOperations[j]) { operationIsAllowed = true; break; } } if (operationIsAllowed) { if (data[i] == '+' && i > 0 && (data[i - 1] == 'E')) { actualNumber += data[i]; continue; } //Debug.Log("Data before: " + data); if (noPrevOperators) { data = data.Remove(0, actualNumber.Length); i = 0; } else { string l1Str = MUtil.ToStandardNotationString(l1); data = data.Remove(i - actualNumber.Length - 1 - l1Str.Length, actualNumber.Length + 1 + l1Str.Length); i -= actualNumber.Length + 1 + l1Str.Length; } noPrevOperators = false; //l1 = l2; //actualNumber = MUtil.ExpNotationToDecimalNotation(actualNumber); if (!DoMaths(ref actualNumber, ref l1, ref l2, ref op, aop, ref firstOperation)) { return("ECONVERSION"); } string standardNotL1 = MUtil.ToStandardNotationString(l1); data = data.Insert(i, standardNotL1); i += standardNotL1.Length; actualNumber = ""; op = aop; //Debug.Log("Data after: " + data); } else { if (data[i] == '+' && i > 0 && (data[i - 1] == 'E')) { actualNumber += data[i]; continue; } if (!double.TryParse(actualNumber, out l1)) { actualNumber = MUtil.ExpNotationToDecimalNotation(actualNumber); if (!double.TryParse(actualNumber, out l1)) { Debug.LogError("Cannot parse " + actualNumber + " to number ( double ) #2"); return("ECONVERSION"); } } op = aop; actualNumber = ""; noPrevOperators = false; firstOperation = false; } } else { actualNumber += data[i]; } } operationIsAllowed = false; for (int j = 0; j < allowedOperations.Length; j++) { if (op == allowedOperations[j]) { operationIsAllowed = true; break; } } if (operationIsAllowed) { if (data[data.Length - 1] == '+' && data.Length > 0 && (data[data.Length - 1] == 'E')) { return(data); } //Debug.Log("l1.ToString(): " + MUtil.ExpNotationToDecimalNotation(l1.ToString()) + ", lenght: " + MUtil.ExpNotationToDecimalNotation(l1.ToString()).Length); string l1Str = MUtil.ToStandardNotationString(l1); data = data.Remove(data.Length - actualNumber.Length - 1 - l1Str.Length, actualNumber.Length + 1 + l1Str.Length); noPrevOperators = false; //l1 = l2; //actualNumber = MUtil.ExpNotationToDecimalNotation(actualNumber); if (!DoMaths(ref actualNumber, ref l1, ref l2, ref op, operations[0], ref firstOperation)) { return("ECONVERSION"); } data = data.Insert(data.Length, MUtil.ToStandardNotationString(l1)); //i += l1.ToString().Length; actualNumber = ""; op = operations[0]; //Debug.Log("Data after: " + data); } return(data); }
/// <summary> /// Calculates data and returns with result multiplied by 100 /// </summary> /// <param name="args">Empty => user would be prompted to write data, args[0] => automatically calculate these</param> static void Main(string[] args) { const bool testMode = false; string dataToCalculate = ""; if (args.Length > 0) { dataToCalculate = args[0]; } else if (dataToCalculate.Length == 0 && !testMode) { while (dataToCalculate.Length == 0) { Debug.Log("Write data to calculate: ", ConsoleColor.White, false); dataToCalculate = Console.ReadLine(); Console.WriteLine(" "); } } if (dataToCalculate.Length == 0 && !testMode) { Debug.FatalError("Data to calculate is empty", -1, 5000); return; } if (dataToCalculate.ToLower() == "f") { Debug.Log("To pay respect", ConsoleColor.Yellow); return; } if (!testMode) { double result = MathFromString.Calculate(dataToCalculate); if (double.IsInfinity(result)) { Debug.LogWarning("Infinity"); } else { Debug.Log("Result: " + MUtil.ToStandardNotationString(result), ConsoleColor.Blue); } } else { double result = 0; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //dataToCalculate = "sqrt(1-(1256^2/1426789^2))/sin(6732+124)"; const double x = 125123.1532; dataToCalculate = "(sqrt(2*" + x.ToString() + "+1)-sqrt(" + x.ToString() + "+6))/(2*" + x.ToString() + "^2-7*" + x.ToString() + "-15)"; int retries = 1; double avg = 0; int repeats = 0; while (true) { //Debug.Log("Test scientific notation: " + MUtil.ToStandardNotationString(2.5)); double mmath = 0; double native = 0; stopwatch.Restart(); for (int i = 0; i < retries; i++) { result = MathFromString.Calculate(dataToCalculate); } stopwatch.Stop(); mmath = stopwatch.ElapsedTicks - 5; //Debug.Log("Result: " + result, ConsoleColor.Yellow); Console.Clear(); Debug.Log("MMathFromString result: " + result, ConsoleColor.Cyan); Debug.Log("Time for " + retries + " retries: " + stopwatch.ElapsedMilliseconds + "ms, " + (stopwatch.ElapsedTicks - 5) + " ticks", ConsoleColor.Cyan); Debug.Log("Time per calculation: " + (stopwatch.ElapsedMilliseconds) / (float)retries + "ms, " + (stopwatch.ElapsedTicks - 5) / (float)retries + " ticks\n", ConsoleColor.Cyan); stopwatch.Restart(); for (int i = 0; i < retries; i++) { //result = MUtil.Power(1500,150) * MUtil.Power(1500, 150) / MUtil.Power(1500, 150); //result = Math.Sin(Math.Pow(4, 1.5)); //result = Math.Sqrt(1 - (Math.Pow(1256, 2) / Math.Pow(1426789, 2))) / Math.Sin(6732 + 124); result = (Math.Sqrt(2 * x + 1) - Math.Sqrt(x + 6)) / (2 * Math.Pow(x, 2) - 7 * x - 15); } stopwatch.Stop(); native = stopwatch.ElapsedTicks - 5; Debug.Log("Native result: " + result, ConsoleColor.Yellow); Debug.Log("Time for " + retries + " retries: " + stopwatch.ElapsedMilliseconds + "ms, " + (stopwatch.ElapsedTicks - 5) + " ticks", ConsoleColor.Yellow); Debug.Log("Time per calculation: " + (stopwatch.ElapsedMilliseconds) / (float)retries + "ms, " + (stopwatch.ElapsedTicks - 5) / (float)retries + " ticks\n", ConsoleColor.Yellow); repeats++; avg += (mmath / native); Debug.Log("\nAbout " + (int)(mmath / native) + "x slower", ConsoleColor.DarkMagenta); Debug.Log("On averge: " + (int)(avg / repeats) + "x slower", ConsoleColor.Magenta); Thread.Sleep(500); } Environment.Exit((int)(result * 100)); } }