public void ExpressionSerializerSerialize() { var parser = new ExpressionSerializer(); ExpressionBase exp; exp = new BinaryOperatorExpression( new NumericExpression(1), new NumericExpression(1), OperatorType.Add); Assert.AreEqual("{1}+{1}", parser.Serialize(exp), "{1}+{1}"); exp = new BinaryOperatorExpression( new NumericExpression(1), new NumericExpression(1), OperatorType.Divide); Assert.AreEqual("{1}/{1}", parser.Serialize(exp), "{1}/{1}"); exp = new BinaryOperatorExpression( new NumericExpression(1), new NumericExpression(1), OperatorType.Multiply); Assert.AreEqual("{1}*{1}", parser.Serialize(exp), "{1}*{1}"); exp = new BinaryOperatorExpression( new NumericExpression(1), new NumericExpression(1), OperatorType.Power); Assert.AreEqual("{1}^{1}", parser.Serialize(exp), "{1}^{1}"); exp = new BinaryOperatorExpression( new NumericExpression(1), new NumericExpression(1), OperatorType.Subtract); Assert.AreEqual("{1}-{1}", parser.Serialize(exp), "{1}-{1}"); }
//a^-n = 1/a^n public static ExpressionBase VariableWithNegativeExponent(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a power. e.g. a^-n BinaryOperatorExpression binaryexpression = expression as BinaryOperatorExpression; if (binaryexpression != null && binaryexpression.Type == OperatorType.Power) { //If exponent of power is unary minus. e.g. -n UnaryMinusExpression unaryexpression = binaryexpression.Right as UnaryMinusExpression; if (unaryexpression != null && binaryexpression.Left != null && binaryexpression.Right != null) { //Return reciprocal of power with unary minus removed in exponent. e.g. 1/a^n BinaryExpression power = new BinaryOperatorExpression(binaryexpression.Left.Clone(), unaryexpression.Expression.Clone(), OperatorType.Power); return new BinaryOperatorExpression(new NumericExpression(1), power, OperatorType.Divide); } } return null; }
public ExpressionBase Parse(List<Token> postFix) { var stack = new ExpressionStack(); ExpressionBase root = null; ExpressionBase left = null; ExpressionBase right = null; foreach (var token in postFix) { switch (token.Type) { case TokenType.Function: root = new FunctionExpression(stack.Pop(), (string)token.Data); stack.Push(root); break; case TokenType.Delimiter: switch (token.Data.ToString()) { case "()": root = new DelimiterExpression(stack.Pop()); stack.Push(root); break; case "{}": root = stack.Pop(); stack.Push(root); break; } break; case TokenType.Number: root = new NumericExpression(int.Parse(token.Data.ToString())); stack.Push(root); break; case TokenType.Constant: root = new ConstantExpression((ConstantType)token.Data); stack.Push(root); break; case TokenType.Variable: root = new VariableExpression((string)token.Data); stack.Push(root); break; case TokenType.Operator: switch (token.Data.ToString()) { case "~": root = new UnaryMinusExpression(stack.Pop()); stack.Push(root); break; case "+": right = stack.Pop(); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Add) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Add, left, right); stack.Push(root); } break; case "-": if (this.TreatMinusAsUnaryMinusInVariadicPlus) { right = new UnaryMinusExpression(stack.Pop()); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Add) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Add, left, right); stack.Push(root); } } else // treat it at binary operator { right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Subtract); stack.Push(root); } break; case "*": right = stack.Pop(); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Multiply) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Multiply, left, right); stack.Push(root); } break; case "/": right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Divide); stack.Push(root); break; case "^": right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Power); stack.Push(root); break; } break; } } return root; }
//1/a^n = a^-n public static ExpressionBase ReverseVariableWithNegativeExponent(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a fraction. e.g. 1/a^n BinaryOperatorExpression binaryexpression = expression as BinaryOperatorExpression; if (binaryexpression != null && binaryexpression.Type == OperatorType.Divide) { //If numerator is 1 and denominator is power. e.g. 1 and a^n NumericExpression numericexpression = binaryexpression.Left as NumericExpression; BinaryExpression power = binaryexpression.Right as BinaryExpression; if (numericexpression != null && numericexpression.Value == "1" && power != null && power.Type == OperatorType.Power) { //return power with minus exponent. e.g. a^-n UnaryMinusExpression unaryminus = new UnaryMinusExpression(power.Right.Clone()); BinaryExpression mysuggestion = new BinaryOperatorExpression(power.Left.Clone(), unaryminus.Clone(), OperatorType.Power); return mysuggestion; } } return null; }
//a*a*...*a = a^n where n is an integer. public static ExpressionBase ProductToExponentRule(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a product. VariadicExpression product = expression as VariadicOperatorExpression; if (product != null && product.Type == OperatorType.Multiply) { //If all operands are equal. if (product.Where((operand) => product[0] == operand).Count() == product.Count) { //Return power. BinaryExpression suggestion = new BinaryOperatorExpression(product[0].Clone(), new NumericExpression(product.Count), OperatorType.Power); return suggestion; } } return null; }
// a*{b/c} = {a*b}/c public static ExpressionBase ProductOfConstantAndFraction(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a product with to operands var variadicExpression = expression as VariadicOperatorExpression; if (variadicExpression != null && variadicExpression.Type == OperatorType.Multiply && variadicExpression.Count == 2) { BinaryOperatorExpression fraction = null; ExpressionBase other = null; //Find which operand is a fraction if ((fraction = variadicExpression[0] as BinaryOperatorExpression) != null && fraction.Type == OperatorType.Divide) { other = variadicExpression[1]; } else if ((fraction = variadicExpression[1] as BinaryOperatorExpression) != null && fraction.Type == OperatorType.Divide) { other = variadicExpression[0]; } else { //Return null of non of the operands is a fraction return null; } //Multiply numerator with other operand VariadicOperatorExpression numerators = new VariadicOperatorExpression(OperatorType.Multiply, fraction.Left.Clone(), other.Clone()); //Return fraction BinaryOperatorExpression suggestion = new BinaryOperatorExpression(numerators.Clone(), fraction.Right.Clone(), OperatorType.Divide); return suggestion; } return null; }
//a/b = a*b^-1 public static ExpressionBase FractionToProductRule(ExpressionBase expression, List<ExpressionBase> selection) { //If expression a fraction. e.g. a/b BinaryExpression fraction = expression as BinaryExpression; if (fraction != null && fraction.Type == OperatorType.Divide) { //Convert denominator to power of -1. b => b^-1 ExpressionBase exponent = new BinaryOperatorExpression( fraction.Right.Clone(), new UnaryMinusExpression(new NumericExpression(1)), OperatorType.Power ); //Return product of numerator and power. a*b^-1 ExpressionBase suggestion = new VariadicOperatorExpression( OperatorType.Multiply, fraction.Left.Clone(), exponent ); return suggestion; } else { return null; } }
//a^c * b^c = (a*b)^c public static ExpressionBase CommonPowerParenthesisRule(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a product. e.g. a^c * b^c VariadicOperatorExpression product = expression as VariadicOperatorExpression; if (product != null && product.Type == OperatorType.Multiply) { ExpressionBase commonPower = null; List<ExpressionBase> baseList = new List<ExpressionBase>(); //Foreach operand in product foreach (ExpressionBase operand in product) { //If operand is a power BinaryOperatorExpression power = operand as BinaryOperatorExpression; if (power != null && power.Type == OperatorType.Power) { //If power's exponent equals the common exponent if (power.Right == commonPower || commonPower == null) { //Add power's base to list commonPower = power.Right; baseList.Add(power.Left); } else { return null; } } else { return null; } } if (baseList.Count > 1) { //Initialize product of all bases in the list. VariadicOperatorExpression resultProduct = new VariadicOperatorExpression(OperatorType.Multiply, baseList[0].Clone(), baseList[1].Clone()); resultProduct.Add(baseList.Skip(2).Select((b) => b.Clone()).ToList()); //return exponent with product as base and common exponent. e.g. (a*b)^c BinaryOperatorExpression result = new BinaryOperatorExpression(resultProduct, commonPower.Clone(), OperatorType.Power); return result; } } return null; }