using System; using System.Collections.Generic; using System.Linq; namespace Lib.Mathematics { public class Expression { internal Expression() { } private List _stacks = new List(); public object Result { get; set; } public string Term { get { return _term; } internal set { _term = value;} } public readonly Dictionary Variables = new Dictionary(); private string _term; public static Expression Parse(string expr) { var returns = new Expression {Term = expr}; expr = expr.Replace("²", "²0"); expr = expr.Replace("³", "³0"); expr = expr.Replace("sqrt[", "√"); expr = expr.Replace("pi", "π"); expr = expr.Replace("]", ""); expr = expr.Replace("√", "1√"); expr = expr.Replace("π", "1π1"); expr = expr.Replace("True", "1"); expr = expr.Replace("False", "0"); expr = returns.Variables.Aggregate(expr, (current, var) => current.Replace(var.Key + "*1", var.Value)); var chars = expr.ToCharArray(); var result = ""; foreach (var c in chars) { if (isNum(c)) { result += c; } else { if (isOP(c)) { returns._stacks.Add(new NumStack(Convert.ToDouble(result))); returns._stacks.Add(new OpStack(c.ToString())); result = ""; } } } returns._stacks.Add(returns.getLastNum(expr)); returns._stacks = returns.dotbeforestatement(returns._stacks); returns.Calculate(); return returns; } internal void Calculate() { for (var i = 0; i < _stacks.Count - 1; i++) { var stack = _stacks[i]; var opStack = stack as OpStack; if (opStack != null) { var first = (NumStack)_stacks[i - 1]; var second = (NumStack)_stacks[i + 1]; var op = opStack; var _result = new NumStack(0); var resultisbool = false; var boolresult = false; switch (op.Value) { case "+": _result = new NumStack(first.Value + second.Value); break; case "-": _result = new NumStack(first.Value - second.Value); break; case "*": _result = new NumStack(first.Value * second.Value); break; case "/": _result = new NumStack(first.Value / second.Value); break; case "^": _result = new NumStack(Math.Pow(first.Value, second.Value)); break; case "%": _result = new NumStack(first.Value % second.Value); break; case "&": _result = new NumStack(Convert.ToDouble(first.Value.ToString() + second.Value.ToString())); break; case "²": _result = new NumStack(first.Value * first.Value); break; case "³": _result = new NumStack(first.Value * first.Value * first.Value); break; case "√": _result = new NumStack(Math.Sqrt(second.Value)); break; case "π": _result = new NumStack(Math.PI); break; case "<": resultisbool = true; boolresult = first.Value < second.Value; break; case ">": resultisbool = true; boolresult = first.Value > second.Value; break; case "!": resultisbool = true; boolresult = first.Value != second.Value; break; } _stacks.RemoveAt(0); _stacks.RemoveAt(0); _stacks.RemoveAt(0); _stacks.Insert(0, _result); Result = (_stacks[0] as NumStack).Value; if (_stacks.Count != 1) { if (_stacks[0] != null && _stacks[1] != null && _stacks[2] != null) { Calculate(); } } if (resultisbool) { Result = boolresult; } } } } #region "ObjectOperators" public static Expression operator +(Expression e1, Expression e2) { return Parse(e1.Result + "+" + e2.Result); } public static bool operator ==(Expression e1, Expression e2) { return e1 == e2; } public static bool operator !=(Expression e1, Expression e2) { return e1 != e2; } public static Expression operator +(Expression e1, string e2) { e2 = e2.Replace("=", ""); return Parse(e2); } public static Expression operator -(Expression e1, Expression e2) { return Parse(e1.Result + "-" + e2.Result); } public static Expression operator *(Expression e1, Expression e2) { return Parse(e1.Result + "*" + e2.Result); } public static Expression operator /(Expression e1, Expression e2) { return Parse(e1.Result + "/" + e2.Result); } public static Expression operator <(Expression e1, Expression e2) { return Parse(e1.Result + "<" + e2.Result); } public static Expression operator >(Expression e1, Expression e2) { return Parse(e1.Result + ">" + e2.Result); } public static implicit operator Expression(string v) { return Parse(v); } public static implicit operator double(Expression instance) { return (double) instance.Result; } public static implicit operator bool(Expression instance) { return (bool) instance.Result; } public static implicit operator string(Expression instance) { return instance.Result.ToString(); } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return false; } return base.Equals(obj); } #endregion #region "Help Functions" private static bool isNum(char s) { double result; return double.TryParse(s.ToString(), out result); } private static bool isOP(char s) { return s == '+' | s == '-' | s == '*' | s == '/' | s == '^' | s == '%' | s == '&' | s == '²' | s == '3' | s == '<' | s == '>' | s == '!' | s == '√' | s == 'π'; } private bool isPunctiaton(char s) { return s == '*' | s == '/'; } private bool isBracketOpen(char s) { return s == '('; } private bool isBracketClosed(char s) { return s == ')'; } private NumStack getLastNum(string s) { var c = s.Split(Convert.ToChar((_stacks[_stacks.Count - 1] as OpStack).Value)); return new NumStack(Convert.ToInt32(c[c.Length - 1])); } private List dotbeforestatement(List st) { var returns = st; for (var i = 0; i < st.Count; i++) { var s = st[i]; if (s is OpStack) { var op = s as OpStack; if (isPunctiaton(Convert.ToChar(op.Value))) { if (st.Count < 3) { var firstop = st[i - 2]; var first = st[i - 1]; var ops = s; var second = st[i + 1]; returns.Remove(first); returns.Remove(ops); returns.Remove(second); returns.Remove(firstop); returns.InsertRange(0, new[] { first, ops, second, firstop }); } } } } return returns; } #endregion #region "Implementations" public override int GetHashCode() { return base.GetHashCode(); } public Expression Clone() { return this; } public override string ToString() { return Result.ToString(); } #endregion } } namespace Lib.Mathematics { public class CalcedStack : Stack { public NumStack first { get; set; } public OpStack op { get; set; } public NumStack second { get; set; } public NumStack result { get; set; } public CalcedStack() { first = new NumStack(0); op = new OpStack(""); second = new NumStack(0); } public override string ToString() { return first.Value.ToString() + op.Value + second.Value.ToString(); } } } namespace Lib.Mathematics { public class NumStack : Stack { public NumStack(double v) : base(v) { } } } namespace Lib.Mathematics { public class OpStack : Stack { public OpStack(string v) : base(v) { } } } namespace Lib.Mathematics { public abstract class Stack : Stack { public t Value { get; set; } protected Stack(t v) { Value = v; } public override string ToString() { return Value.ToString(); } } public abstract class Stack { } }