static void Main(string[] args) { // BigFloat configuration BigFloat.RoundingMode = BigFloat.RoundingModeType.TRIM; BigFloat.RoundingDigits = 4; BigFloat.DefaultPrecision = new Library.Numerics.PrecisionSpec(16, Library.Numerics.PrecisionSpec.BaseType.DEC); /* BigDecimal a = BigDecimal.Parse("1234567865757567"); BigDecimal b = BigDecimal.Parse("1233425678"); BigDecimal n = 15; BigDecimal x, y; x = b * BigDecimal.Log10(a); y = (BigDecimal.Pow(10, x - BigDecimal.Round(x) + n - 1)); Console.WriteLine("Result: {0}*10^{1}\n", BigDecimal.Round(y), BigDecimal.Round(x)); */ Stopwatch Time = new Stopwatch(); string input = "(6/(6x)) + a^(x)/a + 6x/3 + x(x-5)(x+3)(x-54x+54x)x^3 = -4x^5"; MathNode Node = new MathNode(input); Console.WriteLine("\n Equation: {0}", input); MathTree t = new MathTree(Node); // t.Print(); Time.Start(); Node.Simplify(); Time.Stop(); Node.SolveEqual(); Node.Simplify(); // Rearrange the terms Node.Rearrange(); Console.WriteLine("\n Expanded: {0}\n\n", Node.ToString()); /* if (Node.type == NodeTypes.Equal) { Tuple<List<BigFloat>, List<BigFloat>> Roots = Node.Roots(); if (!Object.ReferenceEquals(Roots.Item1, null)) { List<Tuple<BigFloat, BigFloat>> Roots2 = Roots.Item1.Zip(Roots.Item2, (x, y) => Tuple.Create(x, y)).ToList(); bool FirstReal = true; bool FirstImag = true; foreach (Tuple<BigFloat, BigFloat> Real in Roots2.Where(x => x.Item2.IsZero())) { if (FirstReal) { Console.WriteLine("\n\n Real Zero Values: \n"); FirstReal = false; } Console.WriteLine(" x = {0}", Real.Item1); } foreach (Tuple<BigFloat, BigFloat> Imaginary in Roots2.Where(x => !x.Item2.IsZero())) { if (FirstImag) { Console.WriteLine("\n\n Imaginary Zero Values: \n"); FirstImag = false; } Console.WriteLine(" x = {0} + {1}i", Imaginary.Item1, Imaginary.Item2); } Console.WriteLine(); } }*/ }
/// <summary> /// Parse a list of elements into a MathNode /// </summary> /// <param name="Elements"></param> /// <returns></returns> private MathNode ParseString(List<Tuple<string, string>> Elements) { // Remove white-spaces while (Elements.Any() && Elements.First().Item1 == " ") Elements.RemoveAt(0); while (Elements.Any() && Elements.Last().Item1 == " ") Elements.RemoveAt(Elements.Count - 1); // No Elements (?) if (Elements.Count == 0) { return new MathNode(NodeTypes.Empty); } // Remove extra parentheses if (Elements.Any(x => x.Item1 == "(")) { Elements = StripParentheses(Elements); } NodeTypes Type = NodeTypes.Empty; List<Tuple<string, int>> Signs = new List<Tuple<string, int>>(); int insideBrackets = 0; for (int i = 0; i < Elements.Count; i++) { if (Elements[i].Item1 == "(") insideBrackets++; if (Elements[i].Item1 == ")") insideBrackets--; if(insideBrackets == 0) { if (Elements[i].Item2 == ParsedType.Operator.ToString()) { Signs.Add(Tuple.Create(Elements[i].Item1, i)); } } } if (Type == NodeTypes.Empty) { if (Signs.Any(x => x.Item1 == "=")) { Type = NodeTypes.Equal; } else if (Signs.Any(x => x.Item1 == "+")) { Type = NodeTypes.Addition; } else if (Signs.Any(x => x.Item1 == "-")) { Type = NodeTypes.Subtraction; } else if (Signs.Any(x => x.Item1 == "*")) { Type = NodeTypes.Multiplication; } else if (Signs.Any(x => x.Item1 == "/")) { Type = NodeTypes.Division; } else if (Signs.Any(x => x.Item1 == "^")) { Type = NodeTypes.Exponentiation; } } if (Elements.Count == 1 || Type == NodeTypes.Empty) { // --------------------- // Simple MathNode // --------------------- // Number MathNode if (Elements[0].Item2 == NodeTypes.Number.ToString()) { return new MathNode(NodeTypes.Number, new BigFloat(Elements[0].Item1.ToString(), BigFloat.DefaultPrecision)); } // Symbol MathNode if (Elements[0].Item2 == NodeTypes.Symbol.ToString()) { return new MathNode(NodeTypes.Symbol, Elements[0].Item1); } string Result = string.Join(string.Empty, Elements.Select(x => x.Item1)); if (FindFunctionName(Result) != null) { Type = NodeTypes.Function; // Strip "cos" from "cos(3x+6)" // We only need the "cos" ;) Elements = Elements.GetRange(2, Elements.Count - 2); MathNode FunctionMathNode = new MathNode(NodeTypes.Function); FunctionMathNode.symbol = FindFunctionName(Result); FunctionMathNode.AddChild(ParseString(Elements)); return FunctionMathNode; } return new MathNode(NodeTypes.Empty); } else if (Elements.Count > 1) { // --------------------- // Complex MathNode // --------------------- // The result MathNode Main = new MathNode(Type); // --------------------- // Define the splitter character // --------------------- string Splitter = // Simple operators Type == NodeTypes.Addition ? "+" : Type == NodeTypes.Division ? "/" : Type == NodeTypes.Multiplication ? "*" : Type == NodeTypes.Subtraction ? "-" : Type == NodeTypes.Exponentiation ? "^" : Type == NodeTypes.Equal ? "=" : " "; // Debug List<int> SplittersLocations = Signs.Where(x => x.Item1 == Splitter).Select(x => x.Item2).ToList(); if (SplittersLocations.Count == 0) { throw new Exception("Wrongly declared as " + Type + " ( " + Result + " ) "); } SplittersLocations.Add(Elements.Count); for (int i = 0; i < SplittersLocations.Count; i++) { int last = i >= 1 ? SplittersLocations[i - 1] + 1 : 0; Main.AddChild(ParseString(Elements.GetRange(last, SplittersLocations[i] - last).ToList())); } return Main; } return new MathNode(NodeTypes.Empty); }