namespace Equations_Solver
public const string ERROR = "Error!";
public const string ERROR__INVALID_EQUATION = "Equation is not valid!";
public const string ERROR__NEGATIVE_NUMBER_IN_LOG_FUNCTION = "Can't apply 'log' function on a negative number!";
public const string ERROR__NEGATIVE_NUMBER_IN_LN_FUNCTION = "Can't apply 'ln' function on a negative number!";
public const string ERROR__INFINITY_IN_SIN_FUNCTION = "Can't apply 'sin' function on infinity!";
public const string ERROR__INFINITY_IN_COS_FUNCTION = "Can't apply 'cos' function on infinity!";
public const string ERROR__INFINITY_IN_TAN_FUNCTION = "Can't apply 'tan' function on infinity!";
public const string ERROR__NEGATIVE_NUMBER_IN_SQUARE_ROOT = "Can't apply a square-root on a negative number!";
public const string ERROR__NON_WHOLE_EXPONENT_IN_POWER_ON_NEGATIVE_NUMBER = "Can't apply a power with a non-whole exponent on a negative number!";
public const string ERROR__INFINITY_DIVIDED_BY_INFINITY = "Can't divide infinity by infinity!";
public const string ERROR__ZERO_DIVIDED_BY_ZERO = "Can't divide zero by zero!";
public const string ERROR__INFINITY_SUBTRACTED_FROM_INFINITY = "Can't subtract infinity from infinity!";
public const string STEP__ATTEMPTING_TO_SOLVE_THE_EQUATION = "Attempting to solve the equation:";
public const string STEP__SOLVING_EQUATION_INSIDE_PARENTHESES = "Solving equations inside parentheses:";
public const string STEP__REPLACING_THE_RESULT_WITH_THE_PARENTHESES = "Replacing the results with the parentheses:";
public const string STEP__ADDING_MISSING_MULTIPLICATION_SIGNS = "Adding missing multiplication signs:";
public const string STEP__ASSIGNING_THE_VARIABLE_AND_CONSTANTS = "Assigning the variable and constants:";
public const string STEP__SOLVING_FUNCTIONS = "Solving functions:";
public const string STEP__SOLVING_SQUARE_ROOTS = "Solving square-roots:";
public const string STEP__SOLVING_POWERS = "Solving powers:";
public const string STEP__DELETING_ALL_THE_PARENTHESES_FROM_THE_EQUATION = "Deleting all the parentheses from the equation:";
public const string STEP__ADDING_ADDITION_SIGN_BEFORE_SUBTRACTION_SIGNS = "Adding addition sign before subtraction signs:";
public const string STEP__DELETING_DOUBLE_SUBTRACTION_SIGNS = "Deleting double subtraction signs:";
public const string STEP__SOLVING_MULTIPLICATIONS_AND_DIVISIONS = "Solving multiplications and divisions:";
public const string STEP__SOLVING_ADDITIONS = "Solving additions:";
public const string STEP__EQUATION_RESULT = "Equation result:";
public Equation(string equation)
if (!IsEquationValid(equation))
throw new Exception(ERROR__INVALID_EQUATION);
this.equation = equation;
public double Solve(double variable)
if (this.equation == null)
throw new Exception(ERROR__INVALID_EQUATION);
return Solve(this.equation, variable, false, false, 0);
public double Solve(double variable, bool useDegreesInsteadOfRadians)
if (this.equation == null)
throw new Exception(ERROR__INVALID_EQUATION);
return Solve(this.equation, variable, useDegreesInsteadOfRadians, false, 0);
public double Solve(double variable, bool useDegreesInsteadOfRadians, bool printSolvingSteps)
if (this.equation == null)
throw new Exception(ERROR__INVALID_EQUATION);
return Solve(this.equation, variable, useDegreesInsteadOfRadians, printSolvingSteps, 0);
private static double Solve(string equation, double variable, bool useDegreesInsteadOfRadians, bool printSolvingSteps, int scopeLevel)
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ATTEMPTING_TO_SOLVE_THE_EQUATION + " ");
Console.WriteLine(equation);
StringBuilder tempEquation = new StringBuilder();
int parenthesesPairsCount = 0;
int parenthesesNestingLevel = 0;
for (int i = 0; i < equation.Length; i++)
parenthesesNestingLevel++;
else if (equation[i] == ')')
parenthesesNestingLevel--;
if (parenthesesNestingLevel == 0)
int[] parenthesesEquationStartIndexes = new int[parenthesesPairsCount];
int[] parenthesesEquationEndIndexes = new int[parenthesesPairsCount];
parenthesesPairsCount = 0;
parenthesesNestingLevel = 0;
for (int i = 0; i < equation.Length; i++)
if (parenthesesNestingLevel == 0)
parenthesesEquationStartIndexes[parenthesesPairsCount] = i + 1;
parenthesesNestingLevel++;
else if (equation[i] == ')')
parenthesesNestingLevel--;
if (parenthesesNestingLevel == 0)
parenthesesEquationEndIndexes[parenthesesPairsCount] = i - 1;
string[] parenthesesInnerEquationStrings = new string[parenthesesPairsCount];
for (int i = 0; i < parenthesesInnerEquationStrings.Length; i++)
parenthesesInnerEquationStrings[i] = Substring(equation, parenthesesEquationStartIndexes[i], parenthesesEquationEndIndexes[i]);
int parenthesesUnsolvedInnerEquationsCount = 0;
for (int i = 0; i < parenthesesInnerEquationStrings.Length; i++)
if (!IsNumber(parenthesesInnerEquationStrings[i]))
parenthesesUnsolvedInnerEquationsCount++;
if (parenthesesUnsolvedInnerEquationsCount > 0)
if (parenthesesPairsCount > 0)
for (int i = 0; i < scopeLevel; i++)
Console.WriteLine(STEP__SOLVING_EQUATION_INSIDE_PARENTHESES);
double parenthesesInnerEquationResult;
if (parenthesesPairsCount == 1)
tempEquation.Append(Substring(equation, 0, parenthesesEquationStartIndexes[0] - 1));
if (!IsNumber(parenthesesInnerEquationStrings[0]))
parenthesesInnerEquationResult = Solve(parenthesesInnerEquationStrings[0], variable, useDegreesInsteadOfRadians, printSolvingSteps, scopeLevel + 1);
tempEquation.Append(ConvertToString(parenthesesInnerEquationResult));
tempEquation.Append(parenthesesInnerEquationStrings[0]);
tempEquation.Append(Substring(equation, parenthesesEquationEndIndexes[0] + 1, equation.Length - 1));
else if (parenthesesPairsCount == 2)
tempEquation.Append(Substring(equation, 0, parenthesesEquationStartIndexes[0] - 1));
if (!IsNumber(parenthesesInnerEquationStrings[0]))
parenthesesInnerEquationResult = Solve(parenthesesInnerEquationStrings[0], variable, useDegreesInsteadOfRadians, printSolvingSteps, scopeLevel + 1);
tempEquation.Append(ConvertToString(parenthesesInnerEquationResult));
tempEquation.Append(parenthesesInnerEquationStrings[0]);
tempEquation.Append(Substring(equation, parenthesesEquationEndIndexes[0] + 1, parenthesesEquationStartIndexes[1] - 1));
if (!IsNumber(parenthesesInnerEquationStrings[1]))
parenthesesInnerEquationResult = Solve(parenthesesInnerEquationStrings[1], variable, useDegreesInsteadOfRadians, printSolvingSteps, scopeLevel + 1);
tempEquation.Append(ConvertToString(parenthesesInnerEquationResult));
tempEquation.Append(parenthesesInnerEquationStrings[1]);
tempEquation.Append(Substring(equation, parenthesesEquationEndIndexes[1] + 1, equation.Length - 1));
tempEquation.Append(Substring(equation, 0, parenthesesEquationStartIndexes[0] - 1));
if (!IsNumber(parenthesesInnerEquationStrings[0]))
parenthesesInnerEquationResult = Solve(parenthesesInnerEquationStrings[0], variable, useDegreesInsteadOfRadians, printSolvingSteps, scopeLevel + 1);
tempEquation.Append(ConvertToString(parenthesesInnerEquationResult));
tempEquation.Append(parenthesesInnerEquationStrings[0]);
for (int i = 1; i < parenthesesPairsCount; i++)
tempEquation.Append(Substring(equation, parenthesesEquationEndIndexes[i - 1] + 1, parenthesesEquationStartIndexes[i] - 1));
if (!IsNumber(parenthesesInnerEquationStrings[i]))
parenthesesInnerEquationResult = Solve(parenthesesInnerEquationStrings[i], variable, useDegreesInsteadOfRadians, printSolvingSteps, scopeLevel + 1);
tempEquation.Append(ConvertToString(parenthesesInnerEquationResult));
tempEquation.Append(parenthesesInnerEquationStrings[i]);
tempEquation.Append(Substring(equation, parenthesesEquationEndIndexes[parenthesesPairsCount - 1] + 1, equation.Length - 1));
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__REPLACING_THE_RESULT_WITH_THE_PARENTHESES + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__REPLACING_THE_RESULT_WITH_THE_PARENTHESES + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (equation[i] == '(' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*(");
else if (equation[i] == '√' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*√");
else if (equation[i] == 'x' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*x");
else if (equation[i] == 'π' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*π");
else if (equation[i] == 'e' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*e");
else if (IsDigitOrDecimalPointOrInfinitySign(equation[i]) && (equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*" + equation[i]);
else if (i < equation.Length - 1)
if (equation[i] == 'l' && equation[i + 1] == 'n' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*ln");
else if (i < equation.Length - 2)
if (equation[i] == 'a' && equation[i + 1] == 'b' && equation[i + 2] == 's' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*abs");
else if (equation[i] == 'l' && equation[i + 1] == 'o' && equation[i + 2] == 'g' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*log");
else if (equation[i] == 's' && equation[i + 1] == 'i' && equation[i + 2] == 'n' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*sin");
else if (equation[i] == 'c' && equation[i + 1] == 'o' && equation[i + 2] == 's' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*cos");
else if (equation[i] == 't' && equation[i + 1] == 'a' && equation[i + 2] == 'n' && (IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
tempEquation.Append("*tan");
tempEquation.Append(equation[i]);
tempEquation.Append(equation[i]);
tempEquation.Append(equation[i]);
tempEquation.Append(equation[i]);
if (!equation.Equals(tempEquation.ToString()))
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ADDING_MISSING_MULTIPLICATION_SIGNS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ADDING_MISSING_MULTIPLICATION_SIGNS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
tempEquation.Append('(' + ConvertToString(variable) + ')');
else if (equation[i] == 'π')
tempEquation.Append('(' + ConvertToString(Math.PI) + ')');
else if (equation[i] == 'e')
tempEquation.Append('(' + ConvertToString(Math.E) + ')');
tempEquation.Append(equation[i]);
if (!equation.Equals(tempEquation.ToString()))
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ASSIGNING_THE_VARIABLE_AND_CONSTANTS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ASSIGNING_THE_VARIABLE_AND_CONSTANTS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (equation[i] == 'a' && equation[i + 1] == 'b' && equation[i + 2] == 's')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 3] == '(');
for (int j = i + 3; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
double functionResult = Math.Abs(functionArgument);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__NEGATIVE_NUMBER_IN_SQUARE_ROOT);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 3 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
else if (equation[i] == 'l' && equation[i + 1] == 'o' && equation[i + 2] == 'g')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 3] == '(');
for (int j = i + 3; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
double functionResult = Math.Log(functionArgument, 10);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__NEGATIVE_NUMBER_IN_LOG_FUNCTION);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 3 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
else if (equation[i] == 'l' && equation[i + 1] == 'n')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 2] == '(');
for (int j = i + 2; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 1 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
double functionResult = Math.Log(functionArgument, Math.E);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__NEGATIVE_NUMBER_IN_LN_FUNCTION);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
else if (equation[i] == 's' && equation[i + 1] == 'i' && equation[i + 2] == 'n')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 3] == '(');
for (int j = i + 3; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
if (useDegreesInsteadOfRadians)
functionResult = Math.Round(Math.Sin(functionArgument / (180.0D / Math.PI)), 15);
functionResult = Math.Sin(functionArgument);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__INFINITY_IN_SIN_FUNCTION);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 3 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
else if (equation[i] == 'c' && equation[i + 1] == 'o' && equation[i + 2] == 's')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 3] == '(');
for (int j = i + 3; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
if (useDegreesInsteadOfRadians)
functionResult = Math.Round(Math.Cos(functionArgument / (180.0D / Math.PI)), 15);
functionResult = Math.Cos(functionArgument);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__INFINITY_IN_COS_FUNCTION);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 3 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
else if (equation[i] == 't' && equation[i + 1] == 'a' && equation[i + 2] == 'n')
int functionArgumentEndIndex = equation.Length - 1;
bool isFunctionArgumentHasParentheses = (equation[i + 3] == '(');
for (int j = i + 3; j < equation.Length; j++)
if ((isFunctionArgumentHasParentheses && equation[j] == ')') || (!isFunctionArgumentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
functionArgumentEndIndex = j - 1;
string functionArgumentString = Substring(equation, i + 2 + (isFunctionArgumentHasParentheses ? 2 : 1), functionArgumentEndIndex);
double functionArgument = ConvertToDouble(functionArgumentString);
tempEquation.Append(Substring(equation, 0, i - 1));
if (useDegreesInsteadOfRadians)
if (functionArgument % 180 == 90)
functionResult = double.PositiveInfinity;
else if (functionArgument % 180 == -90)
functionResult = double.NegativeInfinity;
functionResult = Math.Round(Math.Tan(functionArgument / (180.0D / Math.PI)), 15);
functionResult = Math.Tan(functionArgument);
if (double.IsNaN(functionResult))
throw new Exception(ERROR__INFINITY_IN_TAN_FUNCTION);
if (double.IsPositiveInfinity(functionResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(functionResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(functionResult) + ')');
tempEquation.Append(Substring(equation, i + 3 + (isFunctionArgumentHasParentheses ? functionArgumentString.Length + 2 : functionArgumentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
if (!tempEquation.ToString().Equals(""))
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_FUNCTIONS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_FUNCTIONS + " ");
Console.WriteLine(" " + ERROR);
for (int i = equation.Length - 1; i >= 0; i--)
int squareRootNumberEndIndex = equation.Length - 1;
bool isSquareRootNumberHasParentheses = (equation[i + 1] == '(');
for (int j = i + 1; j < equation.Length; j++)
if ((isSquareRootNumberHasParentheses && equation[j] == ')') || (!isSquareRootNumberHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
squareRootNumberEndIndex = j - 1;
string squareRootNumberString = Substring(equation, i + (isSquareRootNumberHasParentheses ? 2 : 1), squareRootNumberEndIndex);
double squareRootNumber = ConvertToDouble(squareRootNumberString);
tempEquation.Append(Substring(equation, 0, i - 1));
double squareRootResult = Math.Sqrt(squareRootNumber);
if (double.IsNaN(squareRootResult))
throw new Exception(ERROR__NEGATIVE_NUMBER_IN_SQUARE_ROOT);
if (double.IsPositiveInfinity(squareRootResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(squareRootResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(squareRootResult) + ')');
tempEquation.Append(Substring(equation, i + 1 + (isSquareRootNumberHasParentheses ? squareRootNumberString.Length + 2 : squareRootNumberString.Length), equation.Length - 1));
equation = tempEquation.ToString();
if (!tempEquation.ToString().Equals(""))
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_SQUARE_ROOTS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_SQUARE_ROOTS + " ");
Console.WriteLine(" " + ERROR);
for (int i = equation.Length - 1; i >= 0; i--)
int powerBaseStartIndex = 0, powerExponentEndIndex = equation.Length - 1;
bool isPowerBaseHasParentheses = (equation[i - 1] == ')');
bool isPowerExponentHasParentheses = (equation[i + 1] == '(');
for (int j = i - 1; j >= 0; j--)
if ((isPowerBaseHasParentheses && equation[j] == '(') || (!isPowerBaseHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
powerBaseStartIndex = j + 1;
for (int j = i + 1; j < equation.Length; j++)
if ((isPowerExponentHasParentheses && equation[j] == ')') || (!isPowerExponentHasParentheses && !IsDigitOrDecimalPointOrInfinitySign(equation[j])))
powerExponentEndIndex = j - 1;
string powerBaseString = Substring(equation, powerBaseStartIndex, i - (isPowerBaseHasParentheses ? 2 : 1));
string powerExponentString = Substring(equation, i + (isPowerExponentHasParentheses ? 2 : 1), powerExponentEndIndex);
double powerBase = ConvertToDouble(powerBaseString);
double powerExponent = ConvertToDouble(powerExponentString);
tempEquation.Append(Substring(equation, 0, i - 1 - (isPowerBaseHasParentheses ? powerBaseString.Length + 2 : powerBaseString.Length)));
double powerResult = Math.Pow(powerBase, powerExponent);
if (double.IsNaN(powerResult))
throw new Exception(ERROR__NON_WHOLE_EXPONENT_IN_POWER_ON_NEGATIVE_NUMBER);
if (double.IsPositiveInfinity(powerResult))
tempEquation.Append("(∞)");
else if (double.IsNegativeInfinity(powerResult))
tempEquation.Append("(-∞)");
tempEquation.Append('(' + ConvertToString(powerResult) + ')');
tempEquation.Append(Substring(equation, i + 1 + (isPowerExponentHasParentheses ? powerExponentString.Length + 2 : powerExponentString.Length), equation.Length - 1));
equation = tempEquation.ToString();
i -= (isPowerBaseHasParentheses ? powerBaseString.Length + 2 : powerBaseString.Length);
if (!tempEquation.ToString().Equals(""))
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_POWERS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_POWERS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (equation[i] != '(' && equation[i] != ')')
tempEquation.Append(equation[i]);
if (!equation.Equals(tempEquation.ToString()))
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__DELETING_ALL_THE_PARENTHESES_FROM_THE_EQUATION + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__DELETING_ALL_THE_PARENTHESES_FROM_THE_EQUATION + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (equation[i] == '-' && IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]))
tempEquation.Append("+-");
tempEquation.Append(equation[i]);
tempEquation.Append(equation[i]);
if (!equation.Equals(tempEquation.ToString()))
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ADDING_ADDITION_SIGN_BEFORE_SUBTRACTION_SIGNS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__ADDING_ADDITION_SIGN_BEFORE_SUBTRACTION_SIGNS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (i < equation.Length - 1)
if (equation[i] == '-' && equation[i + 1] == '-')
tempEquation.Append(equation[i]);
tempEquation.Append(equation[i]);
if (!equation.Equals(tempEquation.ToString()))
equation = tempEquation.ToString();
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__DELETING_DOUBLE_SUBTRACTION_SIGNS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__DELETING_DOUBLE_SUBTRACTION_SIGNS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
if (equation[i] == '*' || equation[i] == '/')
int leftNumberStartIndex = 0, rightNumberEndIndex = equation.Length - 1;
for (int j = i - 1; j >= 0; j--)
if (!IsDigitOrDecimalPointOrInfinitySign(equation[j]))
leftNumberStartIndex = j;
leftNumberStartIndex = j + 1;
for (int j = i + 1; j < equation.Length; j++)
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[j]) || equation[j] == '-' && j == i + 1))
rightNumberEndIndex = j - 1;
string leftNumberString = Substring(equation, leftNumberStartIndex, i - 1);
string rightNumberString = Substring(equation, i + 1, rightNumberEndIndex);
double leftNumber = ConvertToDouble(leftNumberString);
double rightNumber = ConvertToDouble(rightNumberString);
tempEquation.Append(Substring(equation, 0, i - 1 - leftNumberString.Length));
double multiplicationResult = leftNumber * rightNumber;
if (double.IsPositiveInfinity(multiplicationResult))
tempEquation.Append("∞");
else if (double.IsNegativeInfinity(multiplicationResult))
tempEquation.Append("-∞");
tempEquation.Append(ConvertToString(multiplicationResult));
double divisionResult = leftNumber / rightNumber;
if (double.IsNaN(divisionResult))
if ((leftNumber == double.PositiveInfinity || leftNumber == double.NegativeInfinity) && (rightNumber == double.PositiveInfinity || rightNumber == double.NegativeInfinity))
throw new Exception(ERROR__INFINITY_DIVIDED_BY_INFINITY);
throw new Exception(ERROR__ZERO_DIVIDED_BY_ZERO);
if (double.IsPositiveInfinity(divisionResult))
tempEquation.Append("∞");
else if (double.IsNegativeInfinity(divisionResult))
tempEquation.Append("-∞");
tempEquation.Append(ConvertToString(divisionResult));
tempEquation.Append(Substring(equation, i + 1 + rightNumberString.Length, equation.Length - 1));
equation = tempEquation.ToString();
i -= (leftNumberString.Length + 1);
if (!tempEquation.ToString().Equals(""))
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_MULTIPLICATIONS_AND_DIVISIONS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_MULTIPLICATIONS_AND_DIVISIONS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < equation.Length; i++)
int leftNumberStartIndex = 0, rightNumberEndIndex = equation.Length - 1;
for (int j = i - 1; j >= 0; j--)
if (!IsDigitOrDecimalPointOrInfinitySign(equation[j]))
leftNumberStartIndex = j;
leftNumberStartIndex = j + 1;
for (int j = i + 1; j < equation.Length; j++)
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[j]) || equation[j] == '-' && j == i + 1))
rightNumberEndIndex = j - 1;
string leftNumberString = Substring(equation, leftNumberStartIndex, i - 1);
string rightNumberString = Substring(equation, i + 1, rightNumberEndIndex);
double leftNumber = ConvertToDouble(leftNumberString);
double rightNumber = ConvertToDouble(rightNumberString);
tempEquation.Append(Substring(equation, 0, i - 1 - leftNumberString.Length));
double additionResult = leftNumber + rightNumber;
if (double.IsNaN(additionResult))
throw new Exception(ERROR__INFINITY_SUBTRACTED_FROM_INFINITY);
if (double.IsPositiveInfinity(additionResult))
tempEquation.Append("∞");
else if (double.IsNegativeInfinity(additionResult))
tempEquation.Append("-∞");
tempEquation.Append(ConvertToString(additionResult));
tempEquation.Append(Substring(equation, i + 1 + rightNumberString.Length, equation.Length - 1));
equation = tempEquation.ToString();
i -= (leftNumberString.Length + 1);
if (!tempEquation.ToString().Equals(""))
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_ADDITIONS + " ");
Console.WriteLine(equation);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__SOLVING_ADDITIONS + " ");
Console.WriteLine(" " + ERROR);
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__EQUATION_RESULT + " ");
Console.WriteLine(ConvertToString(ConvertToDouble(equation)));
for (int i = 0; i < scopeLevel; i++)
Console.Write(STEP__EQUATION_RESULT + " ");
Console.WriteLine(" " + ERROR);
return (ConvertToDouble(equation));
private static bool IsDigitOrDecimalPointOrInfinitySign(char character)
return (character >= '0' && character <= '9') || character == '.' || character == '∞';
private static bool IsArithmeticOpearionSign(char character)
return character == '+' || character == '-' || character == '*' || character == '/';
private static bool IsNumber(string numberString)
for (int i = 0; i < numberString.Length; i++)
if (!(IsDigitOrDecimalPointOrInfinitySign(numberString[i]) || (numberString[i] == '-' && i == 0)))
private static bool IsEquationValid(string equation)
if (equation.Length == 0)
for (int i = 0; i < equation.Length; i++)
if (!IsDigitOrDecimalPointOrInfinitySign(equation[i]))
if (!IsArithmeticOpearionSign(equation[i]))
if (!(equation[i] == '(' || equation[i] == ')'))
if (!(equation[i] == '^' || equation[i] == '√'))
if (!(equation[i] == 'x' || equation[i] == 'π' || equation[i] == 'e'))
if (i <= equation.Length - 3)
if (!(equation[i] == 'l' && equation[i + 1] == 'n'))
if (!(equation[i] == 'a' && equation[i + 1] == 'b' && equation[i + 2] == 's'))
if (!(equation[i] == 'l' && equation[i + 1] == 'o' && equation[i + 2] == 'g'))
if (!(equation[i] == 's' && equation[i + 1] == 'i' && equation[i + 2] == 'n'))
if (!(equation[i] == 'c' && equation[i + 1] == 'o' && equation[i + 2] == 's'))
if (!(equation[i] == 't' && equation[i + 1] == 'a' && equation[i + 2] == 'n'))
int parenthesesNestingLevel = 0;
for (int i = 0; i < equation.Length; i++)
parenthesesNestingLevel++;
else if (equation[i] == ')')
if (parenthesesNestingLevel == 0)
parenthesesNestingLevel--;
if (parenthesesNestingLevel != 0)
for (int i = 0; i < equation.Length - 1; i++)
if (equation[i] == '(' && equation[i + 1] == ')')
for (int i = 0; i < equation.Length; i++)
if (i <= equation.Length - 3)
if ((equation[i] == 'a' && equation[i + 1] == 'b' && equation[i + 2] == 's') ||
(equation[i] == 'l' && equation[i + 1] == 'o' && equation[i + 2] == 'g') ||
(equation[i] == 's' && equation[i + 1] == 'i' && equation[i + 2] == 'n') ||
(equation[i] == 'c' && equation[i + 1] == 'o' && equation[i + 2] == 's') ||
(equation[i] == 't' && equation[i + 1] == 'a' && equation[i + 2] == 'n'))
if (equation.Length - i == 3)
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i + 3]) || equation[i + 3] == 'x' || equation[i + 3] == 'π' || equation[i + 3] == 'e' || equation[i + 3] == '('))
if (i <= equation.Length - 2)
if (equation[i] == 'l' && equation[i + 1] == 'n')
if (equation.Length - i == 2)
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i + 2]) || equation[i + 2] == 'x' || equation[i + 2] == 'π' || equation[i + 2] == 'e' || equation[i + 2] == '('))
for (int i = 0; i < equation.Length; i++)
if (i == 0 && equation[i] == '^')
else if (i == equation.Length - 1)
if (equation[i] == '^' || equation[i] == '√')
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')'))
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i + 1]) || equation[i + 1] == 'x' || equation[i + 1] == 'π' || equation[i + 1] == 'e' || equation[i + 1] == '(' || equation[i + 1] == '√' || equation[i + 1] == 'a' || equation[i + 1] == 'l' || equation[i + 1] == 's' || equation[i + 1] == 'c' || equation[i + 1] == 't'))
else if (equation[i] == '√')
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i + 1]) || equation[i + 1] == 'x' || equation[i + 1] == 'π' || equation[i + 1] == 'e' || equation[i + 1] == '(' || equation[i + 1] == '√' || equation[i + 1] == 'a' || equation[i + 1] == 'l' || equation[i + 1] == 's' || equation[i + 1] == 'c' || equation[i + 1] == 't'))
for (int i = 0; i < equation.Length; i++)
if (IsArithmeticOpearionSign(equation[i]) && equation[i] != '-')
else if (i == equation.Length - 1)
if (IsArithmeticOpearionSign(equation[i]))
if (IsArithmeticOpearionSign(equation[i]) && equation[i] != '-')
if (!(IsDigitOrDecimalPointOrInfinitySign(equation[i - 1]) || equation[i - 1] == 'x' || equation[i - 1] == 'π' || equation[i - 1] == 'e' || equation[i - 1] == ')') ||
!(IsDigitOrDecimalPointOrInfinitySign(equation[i + 1]) || equation[i + 1] == 'x' || equation[i + 1] == 'π' || equation[i + 1] == 'e' || equation[i + 1] == '(' || equation[i + 1] == '√' || equation[i + 1] == 'a' || equation[i + 1] == 'l' || equation[i + 1] == 's' || equation[i + 1] == 'c' || equation[i + 1] == 't'))
else if (IsArithmeticOpearionSign(equation[i]) && equation[i] == '-' && equation[i - 1] == '-')
for (int i = 0; i < equation.Length; i++)
if (equation.Length == 1)
if (!(equation[i + 1] >= '0' && equation[i + 1] <= '9'))
else if (i == equation.Length - 1)
if (!(equation[i - 1] >= '0' && equation[i - 1] <= '9'))
if (!((equation[i - 1] >= '0' && equation[i - 1] <= '9') || (equation[i + 1] >= '0' && equation[i + 1] <= '9')))
for (int i = 0; i < equation.Length; i++)
int numberSegmentStartIndex = 0, numberSegmentEndIndex = equation.Length - 1;
for (int j = i - 1; j >= 0; j--)
if (!IsDigitOrDecimalPointOrInfinitySign(equation[j]))
numberSegmentStartIndex = j + 1;
for (int j = i + 1; j < equation.Length; j++)
if (!IsDigitOrDecimalPointOrInfinitySign(equation[j]))
numberSegmentEndIndex = j - 1;
int decimalPointsCount = 0;
for (int j = numberSegmentStartIndex; j <= numberSegmentEndIndex; j++)
if (decimalPointsCount > 1)
private static string Substring(string str, int startIndex, int endIndex)
return endIndex >= startIndex ? str.Substring(startIndex, endIndex - startIndex + 1) : "";
private static double ConvertToDouble(string numberString)
if (numberString.Equals("∞"))
return double.PositiveInfinity;
if (numberString.Equals("-∞"))
return double.NegativeInfinity;
string[] splitedNumberString = numberString.Split('.');
if (splitedNumberString.Length > 1)
if (splitedNumberString[1].Length > 20)
numberString = splitedNumberString[0] + '.' + splitedNumberString[1].Substring(0, 20);
number = Convert.ToDouble(numberString);
catch (OverflowException e)
return numberString[0] == '-' ? double.NegativeInfinity : double.PositiveInfinity;
private static string ConvertToString(double number)
if (number == double.PositiveInfinity)
if (number == double.NegativeInfinity)
string numberString = "";
double wholeNumber = Math.Truncate(Math.Abs(number));
numberString = (wholeNumber % 10) + numberString;
wholeNumber = Math.Truncate(wholeNumber / 10);
numberString = '-' + numberString;
number = Math.Abs(number);
wholeNumber = Math.Truncate(number);
if (number != wholeNumber)
for (int i = 0; number != Math.Truncate(number); i++)
numberString += (Math.Truncate(number) % 10);
namespace Equations_Solver
public static void Main(string[] args)
Console.Write("Enter equation: ");
string equationString = Console.ReadLine();
Equation equation = new Equation(equationString);
string variableString = "0";
bool isThereAVariableInTheEquation = false;
for (int i = 0; i < equationString.Length; i++)
if (equationString[i] == 'x')
isThereAVariableInTheEquation = true;
if (isThereAVariableInTheEquation)
Console.Write("Enter variable: ");
variableString = Console.ReadLine();
if (variableString != null)
if (!IsVariableValid(variableString))
throw new Exception("Variable is not valid!");
string trigonometricMethodOption = "0";
bool areThereTrigonometricFunctions = false;
for (int i = 0; i < equationString.Length - 2; i++)
if ((equationString[i] == 's' && equationString[i + 1] == 'i' && equationString[i + 2] == 'n') ||
(equationString[i] == 'c' && equationString[i + 1] == 'o' && equationString[i + 2] == 's') ||
(equationString[i] == 't' && equationString[i + 1] == 'a' && equationString[i + 2] == 'n'))
areThereTrigonometricFunctions = true;
if (areThereTrigonometricFunctions)
Console.Write("Enter trigonometric method option ('0' = radians, '1' = degrees): ");
trigonometricMethodOption = Console.ReadLine();
if (trigonometricMethodOption != null)
if (!trigonometricMethodOption.Equals("0") && !trigonometricMethodOption.Equals("1"))
throw new Exception("The specified trigonometric method option is not valid!");
Console.WriteLine("------------------------------------------------------------------------------");
if (variableString.Equals("∞"))
variable = double.PositiveInfinity;
else if (variableString.Equals("-∞"))
variable = double.NegativeInfinity;
else if (variableString.Equals("π"))
else if (variableString.Equals("-π"))
else if (variableString.Equals("e"))
else if (variableString.Equals("-e"))
variable = Convert.ToDouble(variableString);
double equationResult = equation.Solve(variable, trigonometricMethodOption.Equals("1"), true);
Console.WriteLine("------------------------------------------------------------------------------");
Console.Write("Result:");
if (double.IsPositiveInfinity(equationResult))
Console.WriteLine(" Infinity");
else if (double.IsNegativeInfinity(equationResult))
Console.WriteLine(" -Infinity");
Console.WriteLine(" " + equationResult);
Console.WriteLine("------------------------------------------------------------------------------");
Console.Write("Result:");
Console.WriteLine(" NaN");
Console.WriteLine("Error: " + e.Message);
Console.WriteLine("------------------------------------------------------------------------------");
Console.WriteLine("Error: " + e.Message);
private static bool IsVariableValid(string variableString)
if (variableString.Length == 0)
else if (variableString.Length == 1)
if (!(((variableString[0] >= '0' && variableString[0] <= '9') || variableString[0] == '.')))
if (!(variableString[0] == 'π' || variableString[0] == 'e'))
else if (variableString.Length == 2)
if (!(((variableString[0] >= '0' && variableString[0] <= '9') || variableString[0] == '.') && ((variableString[1] >= '0' && variableString[1] <= '9') || variableString[1] == '.')))
if (!((variableString[1] >= '0' && variableString[1] <= '9') && variableString[0] == '-'))
if (!((variableString[1] == 'π' || variableString[1] == 'e') && variableString[0] == '-'))
for (int i = 0; i < variableString.Length; i++)
if (!(((variableString[i] >= '0' && variableString[i] <= '9') || variableString[i] == '.') || (variableString[i] == '-' && i == 0)))
int decimalPointsCount = 0;
for (int i = 0; i < variableString.Length; i++)
if (variableString[i] == '.')
if (decimalPointsCount > 1)