Click here to Skip to main content
15,886,137 members
Articles / Desktop Programming / WPF

Equation Calculator with Graphing

Rate me:
Please Sign up or sign in to vote.
4.92/5 (69 votes)
25 Nov 2010CPOL9 min read 132.7K   4.2K   158  
Equation Calculator with Graphing
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Xml;

namespace CommonUtils
{
	public class EquationParser
	{
		Term m_term = new Term();
		public static string[] FunctionsList 
		{
			get { return Function.FunctionsList;}
		}
		public string Equation {get; private set;}
		public EquationParser()
		{
		}
		public double Value
		{
			get { return m_term.Value; }
		}
		public string ValueAsString
		{
			get 
			{ 
				return Value.ToString();
			}
		}
		public string UsedVarsAsString
		{
			get
			{	StringBuilder sb = new StringBuilder();
				string[] vars = m_term.GetUsedVars();
				foreach (string var in vars)
					sb.AppendFormat("{0}={1}, ", var, Math.Round(m_term.GetVar(var),3));
				return sb.ToString();
			}
		}
		public void SetLastAnswer(double value)
		{
			m_term.SetVar("ans", value);
		}
		public double Calculate(string equation)
		{
			return Calculate(equation, string.Empty);
		}
		public double Calculate(string equation, string variablestring)
		{
			Equation = equation;

			// variable must be a comma seperated list
			if (variablestring.Length > 0)
			{
				foreach (string varstring in variablestring.Split(';'))
				{
					string[] split = varstring.Split('=');
					if (split.Length == 1 && split[0].Trim().Length == 0)
						continue;
					if (split.Length != 2)
						throw new ParseException(variablestring, 0, "string must be a comma seperated list, e.g 'x=10; y=12'");
					string varname = split[0].Trim();
					string vareq = split[1].Trim();
					if (m_term.VarExist(varname))
						throw new ParseException(variablestring, 0, string.Format("Variable {0} already exist", varname));
					Term v = new Term();
					v.Parse(vareq);
					m_term.SetVar(varname, v.Value);
				}
			}
			m_term.Parse(equation);
			return m_term.Value;
		}
		public double CalcForVar(string varname, double varvalue)
		{
			m_term.SetVar(varname, varvalue);
			return m_term.Value;
		}
		string NextWord(string equation, ref int startindex)
		{
			while (startindex < equation.Length && equation[startindex] == ' ')
				startindex++;
			if (startindex >= equation.Length)
				return string.Empty;
			StringBuilder sb = new StringBuilder();
			while (startindex < equation.Length)
			{
				char ch = equation[startindex];
				if (sb.Length > 0 && ch == '=')
					return sb.ToString();
				startindex++;
				if (sb.Length == 0 && ch == '=')
					return "=";
				if (char.IsLetterOrDigit(ch) || ch=='.' || ch=='-')
					sb.Append(ch);
				else
					return sb.ToString();
			}
			return sb.ToString();
		}


		public void Write(XmlTextWriter wr)
		{
			wr.WriteStartElement("eqp");
			wr.WriteElementString("eq", Equation);
			string[] vars = m_term.GetUsedVars();
			if (vars.Length > 0)
			{
				foreach (string var in vars)
				{
					wr.WriteStartElement("var");
					wr.WriteAttributeString("name", var);
					wr.WriteAttributeString("value", XmlConvert.ToString(m_term.GetVar(var)));
					wr.WriteEndElement();
				}
			}
			wr.WriteEndElement();
		}
		public void Read(XmlElement node)
		{
			if (node == null)
				return;
			System.Diagnostics.Debug.Assert(node.Name == "eqp");
			foreach (XmlNode child in node.ChildNodes)
			{
				XmlElement element = child as XmlElement;
				if (element == null)
					continue;
				if (element.Name == "eq")
				{
					Equation = element.InnerText;
					continue;
				}
				if (element.Name == "var")
				{
					string name = element.GetAttribute("name");
					double value = XmlConvert.ToDouble(element.GetAttribute("value"));
					m_term.SetVar(name, value);
				}
			}
			Calculate(Equation);
		}

	}
	public class EquationStack : INotifyCollectionChanged, IList<EquationParser>
	{
		public const string xmlTag = "eqs";
		List<EquationParser> m_stack = new List<EquationParser>();
		public int MaxCount {get; set;}
		public double LastAnswer
		{
			get
			{
				if (m_stack.Count > 0)
					return m_stack[m_stack.Count-1].Value;
				return double.NaN;
			}
		}
		public void Add(EquationParser equation)
		{
			m_stack.Add(equation);
			if (CollectionChanged != null)
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, equation));
			if (m_stack.Count > MaxCount)
			{
				EquationParser old = m_stack[0];
				m_stack.RemoveAt(0);
				if (CollectionChanged != null)
					CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, old, 0));
			}
		}
		public event NotifyCollectionChangedEventHandler CollectionChanged;
		public EquationStack()
		{
			MaxCount = 100;
		}
		public void Write(XmlTextWriter wr)
		{
			wr.WriteStartElement(xmlTag);
			foreach (EquationParser parser in this)
				parser.Write(wr);
			wr.WriteEndElement();
		}
		public void Read(XmlElement node)
		{
			if (node == null)
				return;
			System.Diagnostics.Debug.Assert(node.Name == xmlTag);
			if (node != null)
			{
				foreach (XmlNode child in node.ChildNodes)
				{
					XmlElement element = child as XmlElement;
					if (element == null)
						continue;
					EquationParser parser = new EquationParser();
					parser.Read(element);
					Add(parser);
				}
			}
		}

		#region IList<EquationParser> Members

		public int IndexOf(EquationParser item)
		{
			throw new NotImplementedException();
		}

		public void Insert(int index, EquationParser item)
		{
			throw new NotImplementedException();
		}

		public void RemoveAt(int index)
		{
			throw new NotImplementedException();
		}

		public EquationParser this[int index]
		{
			get
			{
				return m_stack[index];
			}
			set
			{
				throw new NotImplementedException();
			}
		}

		#endregion
		#region ICollection<EquationParser> Members


		public void Clear()
		{
			throw new NotImplementedException();
		}

		public bool Contains(EquationParser item)
		{
			throw new NotImplementedException();
		}

		public void CopyTo(EquationParser[] array, int arrayIndex)
		{
			throw new NotImplementedException();
		}

		public int Count
		{
			get { return m_stack.Count; }
		}

		public bool IsReadOnly
		{
			get { throw new NotImplementedException(); }
		}

		public bool Remove(EquationParser item)
		{
			throw new NotImplementedException();
		}

		#endregion
		#region IEnumerable<EquationParser> Members

		public IEnumerator<EquationParser> GetEnumerator()
		{
			return m_stack.GetEnumerator();
		}

		#endregion
		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return m_stack.GetEnumerator();
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions